From: Bdale Garbee Date: Sat, 28 Mar 2009 12:33:43 +0000 (-0600) Subject: Imported Upstream version 1.7.0 X-Git-Tag: upstream/1.7.0^0 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=06a67e2a5850f36c627b46f330c988e031536ab3;p=debian%2Fsudo Imported Upstream version 1.7.0 --- diff --git a/BUGS b/BUGS deleted file mode 100644 index 67b0797..0000000 --- a/BUGS +++ /dev/null @@ -1,25 +0,0 @@ -Known bugs in sudo version 1.6.9 -================================ - -1) Sudo should have an option to log when removing "dangerous" - environment variables. - -2) On DUNIX in sia mode, hitting return at the prompt does not quit. - -3) In parse.lex, '@' should not need to be a special character. - However, because lex does greedy matching, {WORD} will match - instead of the "^Defaults[:@]?" line. - -4) In list mode (sudo -l), characters escaped with a backslash - are shown verbatim with the backslash. - -5) Because the parser only does a single pass it is possible to - make a sudoers file where the "defaults" options are set after - a user's entry has been validated, changing the permissions for - the user. The work-around is to put all 'defaults' entries - before the "User privilege specification" section but after all - the "alias specifications". In the future the parser will - converted to a two-pass parser. - -6) For the same reason as #5, changing the value of "ignore_dot" has - no effect (find_path() is called before sudoers is parsed). diff --git a/CHANGES b/CHANGES deleted file mode 100644 index 42c7862..0000000 --- a/CHANGES +++ /dev/null @@ -1,2112 +0,0 @@ -CHANGES since sudo 1.2 - -01) sudo now works under hpux, aix, sunos, bsd43, ultrix, linux, osf and irix. - -02) Files w/o the executable bit will be ignored if they are in your PATH. - -03) If execv() fails, perror is called (which prints out an error based on - errno) and sudo exits with -1. - -04) Included in this shar should also be a version of getpass() derived from - the bsd net-2 source which works on bsd, ultrix, hpux, aix, and irix - at least. The latter three unixes have what i consider to be a broken - getpass() in that if /dev/tty can't be opened it doesn't just use stdin - like bsd getpass(). This means you cannot do: rsh host "sudo command" - and have it work if your ticket has expired. - -05) The Makefile has changed significantly. It now has defines for all - supported architectures. - -06) Changed MAXCOMMANDLENGTH from 48 bytes to MAXPATHLEN and included - sys/param.h where appropriate. - -07) Rewrote the code that expands links & paths. It now works correctly. - (rewrote find_path.c) - -08) Added a define NEED_STRDUP so we don't conflict with the system's strdup(3) - -09) Now does *not* pass LD_* environmental vars on to programs that get - exec'd. Also removes SHLIB_PATH for hpux and _RLD_* for dec osf. - -10) Now searches current dir last if '.' or '' are in PATH. Misses braindeath - like './' but if that's in your path you deserve all the trojans you get. - -11) Added in linux patches from drew + flex support. - -12) Added insults back in from original sudo(8) (define USE_INSULTS). - -13) visudo now uses EDITOR envar (from John_Rouillard@dl5000.bc.edu) - -14) you can now specify a dir containing commands that a sudoer can do. - (from John_Rouillard@dl5000.bc.edu) - -15) Ported to Solaris 2.x (based on a port of sudo 1.1 done by UnixOps). - -16) Took out setuid(0); setruid(uid); pairs that bracketed calls to - update_timestamp() since they are unnecessary and setruid() is - broken on systems without a setreuid(2) or setresuid(2) system call. - (Ie: AIX and Solaris 2.x). - -17) The bulk of sudo now runs with the caller's real uid. Grep for - be_root() to find the exceptions. - -CHANGES from sudo 1.3 - -18) Added SECURE_PATH as suggested by russells@ccu1.auckland.ac.nz. - -19) Reworked clean_envp() to modify environ (not envp) so we can use - execvp() safely. - -20) Now use execvp() instead of execve() so sudo /bin/kill works under - broken solaris. This also fixed sudo /etc/fastboot under stock - 4.3 BSD. Basically, this means that any executable shell script that - lacks a '#!/bin/sh' magic number will now work with sudo. Personally - I think that the broken scripts should be fixed rather than changing - sudo, but vendors will be broken. Sigh. - -21) Added USE_EXECV define so you can make sudo use execv() if you - want. Using execvp() shouldn't be a problem since it is always - handed a non-relative path that begins with '/' but some people - may not trust execvp(). - -22) Log file lines will no longer get truncated. Syslog entries that - would overrun the syslog(3) line limit are continued on another entry. - -23) When logging to a log file, long entries are indented to improve - readability. - -24) Whenever the umask is changed, it is changed back to what it was - before. - -25) Log file is written as mode 600 instead of 644 - -26) Umask that sudo runs with may now be specified. - -27) There is now a "configure" script. - -28) Sudo will use ultra fast crypt (ufc) if it finds it for systems w/o - a real crypt(3) (non-US ConvexOS/Secure for instance). - -29) _BSD_COMPAT is now defined for Irix. - -30) The global variable uid is now initialized to -2 because I'm paranoid. - -31) Native Solaris 2 port from Matthew.Stier@aisg.com - -32) Now use sysconf(2) instead of getdtablesize(2) if it is available - (see change #31). Because of the the getdtablesize() emulation for - hpux is no longer necessary. - -33) Now only do a getcwd(3) or getwd(3) once and do it as the real user. - Sudo should no longer complain that it can't get the cwd unless - there is a real problem. - -34) Changed some malloc'd globals of fixed length to be allocated from - the stack instead as there was no win in allocating them from the - heap. - -35) Fixed AIX STATIC_FLAGS as per the AIX faq. - -36) Added -V flag to sudo and visudo (for version) - -37) Now treat EACCESS like EPERM when doing stat(2) in find_path.c - -38) Added prototypes for sudo functions (via __P macro) - -39) configure now uses uname(1) if it exists - -40) gethostbyname(3) is now only called if you define FQDN. There's really - no reason to not trust gethostname(2) and this way if name service is - hosed sudo isn't... - -41) added -v (validate) flag to sudo to update a timestamp w/o running - a command - -42) now use tgetpass() (getpass with a timeout) - -43) find_path() now uses realpath(3) - -44) wrote versions of realpath(3) and getcwd(3) for those without - -45) wrote tgetpass()--a getpass() that times out via select(2) - -46) sudo now uses posix signals if available - -47) Finally added ConvexOS C2 security support from - "Peter A. Nikitser, Systems Software Support, QUT" - -48) You can now #undef MAILER if you don't run sendmail or the equivalent. - -49) AFS support from adamh@austin.ibm.com - -50) If you define BOTH_LOGS in sudo.h you can log both via syslog(3) *ans* - to a log file. - -51) Added ultrix /etc/auth (enhanced security) support. - -52) Sudo now will work with a 4.2BSD syslog (SunOS < 4 && ultrix). - Personally, I'd say you are better off logging to a file if - your syslog is this ancient. - -53) Changed realpath(3) to sudo_realpath() since we need to do the - chdir(2) with the invoking uid. sudo_realpath() should be - faster than vendor-supplied realpath(3)'s anyway... - -54) No longer create a static binary on AIX since it reportedly - causes problem on newer versions on AIX 3.x. - -55) If sudo_realpath cannot chdir() back to cwd sudo will print - and error and exit. Previously it would either fail silently - or print an incorrect error message. - -56) Moved code to send error mail to be after the log message. - From rouilj@cs.umb.edu. - -57) Added SUDO_USER and SUDO_UID envars. Suggested by John P. Rouillard - (. - -62) All .{c,lex,yacc} files now include both sys/types.h and unistd.h so - we are sure to get the typedef of uid_t. - -CHANGES from sudo 1.3.1 - -63) Added preliminary support for DEC OSF/1 protected passwords - (shadow passwords). - -CHANGES from sudo 1.3.1pl1 - -64) More support for DEC OSF/1 protected passwords (shadow passwords). - -CHANGES from sudo 1.3.1pl2 - -65) Fixed mail logging to include the username as it should have. - -66) Added hostname to log message in error mail. - -67) Added -l flag to sudo to list the allowed/forbidden commands. - Suggested by matthew@gateway.bsis.com (Matthew Stier) - -68) Fixed bison warnings for parse.yacc and visudo.yacc. - Pointed out by alfie@dcs.warwick.ac.uk (Nick Holloway). - -CHANGES from sudo 1.3.1pl3 - -69) Sudo will now exit with an error if the command to be run is > MAXPATHLEN. - -70) Test in configure for termios support was insufficient. It thought - Nextstep 3.2 had termios just because it as termios.h (need to link - with -posix for termios on NeXT's) - -CHANGES from sudo 1.3.1pl4 - -71) First stab at Skey support. - -72) Sudo now sets IFS to be SPACE, TAB, NEWLINE. - -73) Sudo now sets the real and effective gid to root's group - (based on passwd file). - -74) Sudo now checks that the sudoers file is owned by a certain user - and not readable or writable by anyone else. - (based on a suggestion by Joerg Schumacher ) - -75) Visudo now sets the owner on the new sudoers file based on #74 - -76) Sudo and visudo will now compile with byacc (Berkeley yacc). - -77) If the rename(2) of stmp -> sudoers fails /bin/mv is executed before - bailing. Based on code from Case Larsen . - -78) User-level configuration is now done in options.h. - -79) Moved all compatibility #defines to compat.h - -80) Incorporated new parsing code from Chris Jepeway . - This is much better than the previous parser. - -81) Rewrote visudo.c and tickled parse.yacc to work with it. Visudo - now gives you options if a parse error occurs rather than blindly - dumping you back in the editor. - -82) Took out all references to realpath since we are now checking based - in inode and device (with Chris' new parser). The upshot of this - is that path matches are done safely and the symlink problem has - gone away. - -83) Fixed bison warnings from new parse.yacc. - -84) Added a default case to parse.lex to error on unmatched tokens as Chris - suggested. - -85) Converted configure.in and acsite.m4 to autoconf 2.1. - -86) Added lsearch.c and search.h for os's w/o lsearch()/lfind(). - -87) Sudo now checks to see that the file it is executing is a regular file - (was just checking the execute bit so dirs slipped through). - Pointed out by Barb Dijker . - -88) Fixed a problem on HP-UX trusted systems with getpwuid() returning "*" - unless the real uid is 0. Reported by Brian Cunnie (cunnie@nyc.hp.com). - -89) configure now checks for size_t and ssize_t in unistd.h as well - as sys/types.h. - -90) configure now checks for egrep before actually using it. - -91) configure now checks for a working void implementation (ie: void * as - a generic pointer) and sets VOID to void or char accordingly. - -92) Added support for SunOS 4.x C2 security (shadow passwords) from - Kendall Libby (fubar@shore.net) - -93) Changed all occurrences of bzero() to memset() and bcopy() to - memmove(). - -94) Fixed a bug in sudo.c. If a user has no passwd entry sudo would - dump core (writing to a garbage pointer). Pointed out by - Stephen Schaefer . - -95) Worked around a bug in AIX's lex in parse.c. AIX lex doesn't seem - to handle {x,y} range notation correctly. Bleah. - -96) Sudo would not report a failed attempt if the user entered return - at the 2nd password: prompt so someone trying to guess a password - could just invoked sudo multiple times and try one passwd at a time. - Reported by Jonathan Adams . - -97) Added User_Alias facility. - -98) Rewrote most of the ip address / network support. Now works on all - systems sudo has currently been tested on. - -99) Sudo now sets SUDO_COMMAND and SUDO_GID envariables in addition to - SUDO_USER and SUDO_UID. - -100) Added changes to configure.in for UnixWare. - (from John Warburton ) - -101) Merged in changes for Interactive Unix and RISCos. - (from Andy Smith ) - -102) Added testsudoers (from Chris Jepeway ). - -103) Added fix for parse.yacc to avoid the kludge I was doing. - (from Chris Jepeway ) - -104) Now remove the IFS envar if set instead of setting it to a "safe" - value to avoid problems with make and others. - -105) Added FAST_MATCH option to check basenames of sudo command and - paths listed in sudoers file. If the basename doesn't match - then it is not a match. If the basename matches, then do - a stat to make sure it is a valid match. - -106) Now only stat(2) cmnd once in path_matches() (in parse.c). Sudo - was stating cmnd for *every* attempted match. Now the stat struct - is cached (ie: the var is a static). - -107) Signal handlers in visudo are now only installed after the stmp - file is opened. Previously, it was possible to erase an open - stmp file by sending visudo a signal within a small window. - -108) Added Goon Show insults from Russell Street . - -109) Broke out the insults into separate include files (insults.h - is the master and includes the appropriate one). - -110) Now use getwd() instead of getcwd() and provide emulation for - OS's w/o it. This was done since some OS's with getwd() - implement getcwd() via a pipe to pwd(1). By emulating getwd() - by calling getcwd() on OS's w/o getwd() we lose nothing since - the compiler should optimize away the extra function call. - -111) Added crypt() for DEC OSF/1 3.x enhanced security. - From "Richard L Jackson Jr" . - -112) Added an option to run the command in the background (-b) as - suggested by Jonathan Adams - -113) First stab at kerberos support. I'm not really sure it is - possible to do this in a sane manor. Sigh. - -114) Better kerberos support. Had to use setreuid(2) but falls - back on a kludge if that does not exist or is broken. - -115) Added -p (password prompt) support. - Suggested by "David W. Cooley" - -116) Added partial implementation of -l (list) flag. - This is probably as good as it will get until sudo:tng. - -117) Added anti-spoofing code to tighten up a race condition - where a user could run sudo some_link and then change - where the link pointed after the old link had been - validated but before the exec(). - -118) Now update timestamp file via utime() (and emulate via utimes() - if necessary) to eliminate a small race. Works with - both POSIX utime() as well as old utime() in BSD <= 4.3. - -119) Kerberos ticket file now lives in same dirs as sudo timestamp - files (to avoid trouncing on normal ticket file) and is removed - after validation. - -120) Now log tty user is on as well as pwd in sudo logs. - -CHANGES from sudo 1.3.2 BETA - -121) Fixed a bug in the anti-spoofing check. - -122) Fixed up ISC support so that it works and looks like non-streams - stuff in interfaces.c. - -123) Now deal correctly with ip implementations that has an sa_len - field in struct sockaddr. - -124) Check ownership and permissions on timestamp dir and ignore if - not owned by root and mode 0700. Problem pointed out by Larry Auton - and Navjot Singh . - -125) Ignore timestamp files with preposterous dates to keep people from - faking out sudo on OS's that allow you to give away files to root. - Problem pointed out by Larry Auton and - Navjot Singh . - -126) A timeout of 0 will now cause a password to be entered every - time. Based on a suggestion by Larry Auton - and Navjot Singh . - -CHANGES from sudo 1.3.3 BETA - -127) Cleaned up interfaces.c so that it is more readable. - -128) Added support for syslog()'s that don't guarantee delivery - of a message. HP-UX is the only known offender. - -129) No longer use memmove() since memcpy() does what we need and - configure doesn't always catch memmove() even when it is - there (may be a library problem). - -130) Updated man page to reflect two more security issues. - -131) Cleaned up shadow password support in check.c. It should now - be readable. - -132) Added SCO support. - -133) Added check to configure to find the max length of a uid_t - in characters. - -134) Removed uid2str() since we now know how big a uid_t/gid_t - can be. This elminates a few malloc()'s. - -135) Added support for multiple insult types. Based on code and - a suggestion from Dieter Dworkin Muller . - -136) Replaced clean_env() and rmenv() with a rewritten clean_env() - that should be a little faster. This also makes it easier to - add to the list of "dangerous" envariables. - -137) Added netgroup support. Netgroups must start with a leading - "+" to that sudo knows it is a netgroup. - -138) Split out sudoers file format into its own man page. - As suggested by Andy Smith . - -139) Updated testsudoers.c to grok netgroups. - -CHANGES from sudo 1.3.4 BETA - -140) Added SecurID support from Giles Todd . - -141) Added -s flag to start a root shell and -- to signify end of args. - -142) Sped up logging routines by replacing strncpy()'s with strcat()'s. - This is safe because we dyanically allocate logline to be big enough. - -143) Now support command line arguments in the sudoers file. - -144) Sped up the loading on command line arguments. This fixes the - "commands with large argc's take forever to run" bug. - -145) Expanded MAXCOMMANDLEN to 8K since we now have to deal with - command line arguments. Added bounds checking in fill() and - append() so we don't drop core. - XXX - 8k makes sudo *SLOW* - -146) Added support in the lexer for "termination characters" to be - escaped. Ie: you can now use [\,:=] in command line args - as long as you escape with a \. - -147) Testsudoers can now deal with commands that have arguments. - -148) If a file is not executable or not a regular file sudo will - now give the appropriate error message instead of just - "command not found" which is misleading. - -149) Fixed a bug where if FQDN is set, load_interfaces() was never - called. - -150) tty is now a global so it can be used in the ticket file - at a later date. - -151) Strings in the parser are now allocated dynamically. This results - in a large speedup as compared to a 1K array on the stack. I - have freed the strings in the parser where appropriate but that - may not catch all instances. Even so, the average sudo now - takes up less memory than the 1K array version. - -152) Fixed a bug in tgetpass() and configure that broke termio/termios - support for some OS's. - -153) Added cheapo implementation of tty-based timestamps. The correct - way is to have username be a directory with the tty tickets - inside. However, the current code does not take to that very - well, and it does not allow the two systems to coexist. Therefore, - instead of timestampdir/user/tty it is timestampdir/user.tty. - -154) Added support for building in other than the source directory. - Based on changes from "Simon J. Gerraty" - -155) options.h and pathnames.h are now included via angle brackets - (<>) so as to use the -I include path. This way, those using - a shadow build tree may have local copies of these headers - w/o clobbering the distribution ones. - -156) EXEMPTGROUP is now a string (group name) and user_is_exempt() - is now less of a hack. It uses getgrnam(EXEMPTGROUP) to - get a list of users in the exempted group. - -157) --prefix and --exe_prefix are now honored in the Makefile. - -158) Sudo will now behave reasonably in the case where the sudoers - file location is mounted via NFS and the client does not - have "root" NFS privs. - -159) _PATH_SUDO_SUDOERS, _PATH_SUDO_STMP, and SUDOERS_OWNER are - now set via the Makefile since that appears to be what - most people expect... - -160) Now include a pre-generated version of parse.lex since so many - versions of lex are brain damaged. If parse.lex is changed - a new lex.yy.c will be generated. The distribution copy is - sudo-lex.yy.c. - -161) Upgraded to GNU autoconf version 1.5. There are now even - *more* options. - -CHANGES from sudo 1.3.5 BETA - -162) Fixed S/Key support. - -163) Cleaned up shadow password support further by moving much of - it to getspwuid.c. - -164) First cut at DCE support. [needs work to be functional] - -165) New Digital UNIX C2 support based on code from - "Randy M. Hayman" - -166) S/key support now works with the generic bellcore s/key - as well as the s/key from Wietse Venema's logdaemon. - (Previously only worked with the logdaemon s/key). - As an added bonus the s/key challenge is now embedded - in the password prompt for a cleaner look. - -167) lsearch.c will now compile on a strict ANSI C compiler. - ANSI doesn't allow pointer arithmetic on a "void *" - but gcc does. - -168) Bought back latest HP-UX DCE support from Jeff Earickson - . - -169) configure now comletely groks $SUDO_LIBS and $VISUDO_LIBS. - Plain old $LIBS is no longer used. LDFLAGS has also been - split up into $SUDO_LDFLAGS and $VISUDO_LDFLAGS. - The reason for this is that sudo often needs extra libs - for alternate authentication schemes but visudo rarely does. - -170) The code to copy command arguments flaied for large values of - argc due to realloc() lossage. We now cheat and treat argv[] - as a flat string (since that's what it is) and use pointer - arithmetic to compute the length. Kind of sneaky but it - works (and is relatively fast). - -CHANGES from sudo 1.3.6 BETA - -171) Added support for UN*X groups in sudoers based on code from - Dougal Scott . - -172) interfaces.c should work on ISC UN*X again. - -173) All source files are <= 14 characters for old SYSV file systems. - -CHANGES from sudo 1.3.7 GAMMA - -174) Minor configure[.in] fixes. - -175) tgetpass.c now compiles on OS's that put the definition of - fd_set in - -CHANGES from sudo 1.4 - -176) Command args in sudoers are now stored in an argument vector - instead of a flat string to make wildcard matching simpler. - -177) Added NewArgv and NewArgc that describe the command to be - executed. The copy of args in cmnd_args is no longer necessary - and has been removed. - -178) Using strcmp(3) for argument matching in command_matches() - (was path_matches()) is no longer sufficient since we don't - have a flat string. compare_args() is used instead which - calls either strcmp(3) or wildmat(3l) depending on whether - there are shell-style meta chars (wildcards) present. - -179) Shell-style wildcard matches are now available in the sudoers - file. Matches are done via Rich $alz's wildmat(3). - This required the tweaks described in #176-178 as well as - other, more minor, changes. - -180) Commented out rule to build lex.yy.c from parse.lex since - we ship with a pre-flex'd parser and can't rely on file - dates being set correctly. - -181) Fixed visudo and testsudoers to deal with new argument - vector handling. - -182) A null string ("") as shell in passwd file (or $SHELL) is - now treated as the bourne shell. - -183) Converted *.man to pod format for easy conversion to man, - html, latex, and just plain text. Tried to make the - sudoers manual easier to read in the process. - -184) Updated sample.sudoers and sudoers.pod to include info - on wildcards. - -CHANGES from sudo 1.4.1 - -185) compat.h now defines _PASSWD_LEN based on PASS_MAX if it - is defined (from limits.h on SYSV). - -186) Both short and long hostnames may now be used in the sudoers - file if FQDN is defined. From patches submitted by - Michael Meskes . - -187) Now use skeylookup() instead of skeychallenge(). Hopefully - this will work around a problem some people have reported - on Solaris 2.5 with sudo and logdaemon 5.0's skey. - -188) Now uses /var/run to hold timestamp files if it exists. This - is more secure. - -189) configure now puts the timestamp dir in /var/run if it exists. - Sugestion by Michael Meskes . - -190) Both short and long hostnames now exist even if FQDN is not set. - This allows machines with fully qualified hostnames set via - hostname(1) to use them in the sudoers file. - -191) sudo was not honoring "." in $PATH due to a bug in find_path(). - -192) Added IGNORE_DOT_PATH option to ignore "." in $PATH. - -193) tgetpass() now uses raw read(2) and write(2) instead of stdio. - This should make it work on more OS's. Previously, it used - stdio (buffered) fgets(3) and fputs(3) with select(2) which - may not be legal. Also got rid of the nasty goto's and - generally simplified the code. - -194) Parser now supports hostnames like UPPERCASE.foo.com. Previously, - `UPPERCASE' was interpreted as an Alias. This means that - the `fqdn' stuff has been moved to the lexer (FQHOST is used - to avoid collision with FQDN option). - -195) Reworked --with-FOO in configure.in to support --without-FOO. - Made shadow passwords the default for appropriate OS's. They - can be turned off with --without-C2. - -196) Added NO_PASSWD option for those who don't want to be bothered - by a password prompt from sudo. This is really just a hack. - -197) Added support for double quotes to mean "treat these words as one - argument". This is similar to what most shells do. - -198) Added mkinstalldirs to make install destination dirs if - they do not already exist. - -CHANGES from sudo 1.4.2 - -199) Added support for --with-CC (which C compiler to use). - -200) Added support for NOPASSWD token and running commands a - specified users (sudo -u) from Keith Garry Boyce - - -201) Only link with -lshadow for Linux if libc lacks getspnam(). Problem - pointed out by Michael Meskes . - -202) Replaced SUDOERS_OWNER with SUDOERS_UID and SUDOERS_GID. Added - SUDOERS_MODE and changed the default to 0440 (from 0400). - It is now possible to NFS-mount sudoers without doing anything fancy. - -202) If a runas list is specified, a user may only run commands as - "root" if "root" is a member of the runas list. The old behavior - was to always allow commands to be run as root, even if a runas - list was specified. Now you can give someone "sudo -u operator" - and not have the equivalent of "sudo -u root" as well. - -203) Added "USER=%s" to logging functions. - -204) configure will now add -lPW to (VI)?SUDO_LIBS if using bison - or DCE and alloca(3) is not in libc (or provided by gcc) but - is in libPW.a. - -205) sudo would give an incorrect error message if the sudoers file - didn't exist due to close() stomping errno if the open() failed. - -206) Fixed "shell" mode (sudo -s). When building NewArgv sudo was - not allocating space for the NULL. - -207) Added support for wildcards in the pathname. Ie: /bin/*. - -208) 'command ""' in sudoers now means no args allowed. - -209) Added command line args to SUDO_COMMAND envariable. - -210) HP-UX 10.x with C2 now uses bigcrypt(). - Changes from david_dill@Merck.Com (David Dill). - -211) lsearch.c will now compile w/o compiler warnings. - (Updated from NetBSD lsearch.c) - -212) Now uses POSIX fnmatch(3) (which uses ! instead of ^ in ranges) - -CHANGES from sudo 1.4.3 - -213) Now allows network/netmask in sudoers to override per-interface - netmask. - -214) Fixed -u support with multiple user lists on a line. - -215) Fixed a core dump problem when built with -DSHELL_IF_NO_ARGS. - -216) Fixed 2 typos in parse.yacc and removed some unnecessary if's. - -217) Now always use install-sh since SunOS install can't do uid/gid's. - Other BSD installs are probably similarly afflicted. - -218) Fixed NFS-mounted sudoers file under solaris both uid *and* gid - were being set to -2. Now set uid to 1 to avoid group being - remapped. - -219) Now includes alloca.c (from gcc) for those w/o it. Linking - against -lPW breaks visudo on HP-UX and probably others. - -220) Added --with-libpath, --with-libraries, --with-incpath options - to configure. - -221) configure now uses shicc instead of gcc on BSD/OS >= 2.0 to - generate binaries linked with shared libs. - -222) The parser was setting no_passwd even if there wasn't a - runas match. I reordered some things in parse.yacc - to fix this. - -223) `sudo -v' (validate) wasn't paying attention to NOPASSWD. - Now it does. - -224) testsudoers now groks "-u user". - -225) Updated AFS support based on what tcsh 6.06 does. - -226) Fixed a typo/thinko that broke BSD > 4.3reno wrt interfaces.c. - -227) HPUX 10.X shadow password stuff now uses SecureWare routines. - -228) SecureWare passwd checking now uses bigcrypt() if available. - Now uses AUTH_MAX_PASSWD_LENGTH if defined. - -229) configure now makes sure you don't have a config.cache file - from another OS. - -230) Added better shadow password detection. - BSD >= 4.3reno -> /etc/master.passwd - hpux9: getspwnam() -> /.secure/etc/passwd - hpux10: getspnam() or getprpwnam() -> /tcb/files/auth/*/* (link with -lsec) - SVR4: getspnam() -> /etc/shadow - solaris: getspnam() -> /etc/shadow - irix[56].x: getspnam() -> /etc/shadow - sunos 4.x: getpwanam() -> /etc/security/passwd.adjunct - DUNIX: getprpwnam() -> /tcb/files/auth/*/* (link with -lsecurity) - SecureWare: getprpwnam() -> /tcb/files/auth/*/* - ultrix 4.x: getauthuid() -> /etc/auth.{pag,dir} - -231) '(' in command args no longer are a syntax error. - -232) '!command' now works in the presence of a runas or NOPASSWD token. - Simplified parse rules wrt runas and NOPASSWD (more consistent). - -233) Command args and now compared as a flat string again. This makes - wildcard matches more consistent. - -234) DUNIX C2 support now groks AUTH_CRYPT_OLDCRYPT and AUTH_CRYPT_C1CRYPT. - -235) configure now uses config.{sub,guess} to guess OS type. - Sudo should work out of the box on more OS's now. - -236) Got rid of HAVE_C2_SECURITY, now just use SHADOW_TYPE. - -237) Fixed race in tgetpass() where echo can be turned off and - left off if sudo is used in a pipeline and a password is - required. - -CHANGES from sudo 1.4.4 - -238) `sudo -l' output now includes runas and NOPASSWD info and - asks for a password unless NOPASSWD for ALL is set. - -239) Sudo can now deal with all-caps user and host names. - -240) Sudo will now remove the "ENV" and "BASH_ENV" envariables. - From Michael Meskes . - -241) `sudo -l' will now expand Cmnd_Alias's (could be prettier). - -242) `sudo -s' will now set $HOME to root's homedir (or that of - the user specified -u) so dot files get sourced. - -CHANGES from sudo 1.4.5 - -243) $HOME was always being set, not just with `-s'. - -244) In visudo, the owner and group of the sudoers file were - being set too early; an editor could change them and change - the owner/group of the resulting sudoers file. - -CHANGES from sudo 1.5 - -245) Added SHELL_SETS_HOME option. - -246) Added NO_MESSAGE option. - -247) Added %u and %h escapes in PASSPROMPT to expand to user's name - and host. - -248) Added "SUDO_PROMPT" envariable. - -249) Usernames may now begin with a digit. Gross, but people do it. - -Sudo 1.5.1 released. - -250) Added `opie' support. - -251) Added check to make sure fnmatch() really works. - -252) Now use the prompt S/Key gives us instead of rolling our own. - -253) Added -H flag from Danny Barron . - -254) Add SUDO_PS1 envariable support. - -255) Attempt at sequent support. - -Sudo 1.5.2 released. - -256) visudo acts sanely when there is no sudoers file. - -257) Added Runas_Alias support. - -258) Sudo will now work with SUDOERS_MODE == 400 and SUDO_UID = 0. - -259) Alias's in a runas list are now expanded. - -260) Fixed bug with > 32 saved aliases. Reported by BHH@capgroup.com. - -261) Code that uses sprintf() is now more paranoid about buffer - overflows. - -262) Whitespace is now allowed after a line continuation character before - a newline in sudoers. - -263) %h in MAILSUBJECT expands to local hostname. - -Sudo 1.5.3 released. - -264) Don't pass getdtablesize() as first arg to select(2). No need - to do this since we only select on one fd--use (fd+1) as nfds - and the old way caused problems on some systems (arguably - a bug in those OS's). From Marc Slemko marcs@znep.com. - -265) Fixed coredump when passwd file is missing or unavailable. - Reported by Jason Downs and - Klee Dienes (via a Debian Linux bug report). - -266) Fixed bug wrt exclusion lists and relative pathnames. - Reported by osiris@COURIER.CB.LUCENT.COM. - -267) exit(1) if user doesn't enter a passwd. - Noted by Alex Parchkov . - -Sudo 1.5.4 released. - -268) Newer versions of Irix use _RLDN32_* envariables for 32-bit binaries - so ignore _RLD* instead of _RLD_*. From tarrall@bamboo.Colorado.EDU. - -269) Only open sudoers file once as opposed to once for sanity checks and - once for the parser. Also try to open ten times if we get EAGAIN. - -Sudo 1.5.5 released. - -270) Initialize group vector if we are becoming a user other than root. - For root, it is often more useful to hang on to our existing group - vector. - -271) Fix usage of select(2) to deal correctly with a high-numbered fd. - -272) Fixed a bug where sudo sometime didn't give the user a chance to - enter a password at the prompt. - -273) Use a dynamically sized buffer when reading ether interfaces. - -274) Fixed configure problems with identification of HP-UX > 10.x and - with cc being identified as a cross compiler on some platforms. - -275) Fixed a problem with HP-UX 10.x and alloca. Bison does not - include alloca.h on HP-UX 10.x even though it uses alloca() - (and thus needs the #define of alloca(x) to __builtin_alloca(x)). - To fix this we include alloca.h ourselves if using bison and not gcc. - -276) Included support for the AIX 4.x authenticate() function from - Matt Richards . - -277) Fixed an off by one error in the parser. Found by - Piete Brooks - -278) Change NewArgv size computation to work on UNICOS. - From Mike Kienenberger - -279) Added --with-logfile and --with-timedir configure options. - -280) Use getcwd(3), not getwd(3) to avoid possible buffer overflow. - Use BSD getcwd(3) if system lacks one or is SunOS 4.x. - -281) Fix 'fprintf' argument mismatches in 'visudo.c'. - From ariel@oz.engr.sgi.com (Ariel Faigon) - -282) Use waitpid or wait3 to reap children in logging.c. - Pointed out by Theo de Raadt - -283) Sudo should prompt for a password before telling the user that - a command could not be found. Noted by rhodie@NAC.NET. - -284) Fix OTP_ONLY for opie; "Deven T. Corzine" . - -285) Include pre-yacc'd parse.yacc as sudo.tab.[ch] since more and - more vendors are charging for yacc (bad vendor, no cookie). - -286) Use MAX*, not MAX*+1 - -287) Add support for Hitachi SR2201, from b-edgington@hpcc.hitachi-eu.co.uk - -288) Added RUNAS_DEFAULT option to allow one to compile sudo with a - default runas user other than root. - -289) Add options to log the hostname in the file-based log and to not - do word wrap in file-based log. From Theo Van Dinter - -290) RedHat Linux pam support, from Gary Calvin . - pam.sudo goes in /etc/pam.d/sudo on RedHat 5.0 and above. - -291) With sudo -s, set command the full path of the shell, not the basename. - Noted by Peter W. Osel - -Sudo 1.5.6 released. - -292) Pam auth now runs as root; necessary for shadow passwords. - -293) Shadow password support is now compiled in by default. You can disable - it via --disable-shadow. - -294) We now remove a timestamp file with a bogus date when it is detected. - From Steve Fobes . - -295) In tgetpass(), restart select if it is interrupted. This really fixes a - problem where a user sometimes is not given a change to enter a password. - -296) All options have moved from options.h -> configure. - -297) visudo is now installed in /usr/local/sbin where it belongs. - -298) Lots of configure changes. Instead of checking for the existence - of -lsocket, -lnsl, or -linet, we instead check them for the - functions we need only if they are not already in libc. - -299) Added DUNIX SIA (Security Integration Architecture) support from - Spider Boardman . - -300) Added test for broken Digital UNIX 4.0 prot.h. - -301) Better support for C2 security on Digital UNIX. - -302) Hacked autoconf so that you have have single quotes in - --with-passprompt. - -303) For SecureWare-style shadow passwords use getprpwnam() instead - of getprpwuid() since getprpwuid is broken in HP-UX 10.20 at - least (it sleeps for 2 minutes if the shadow files don't exist). - -304) We can't really trust UID_MAX or MAXUID since they may only exist for - backwards compatibility; spider-both@Orb.Nashua.NH.US - -305) Make %groups work as RunAs specifiers; Ray Bellis . - -306) Set USER environment variable to target user. - Suggested by Ray Bellis . - -307) Go back to printing "command not found" unless --disable-path-info - specified. Also, tell user when we ignore '.' in their path and it - would have been used but for --with-ignore-dot. - -308) When using tty tickets make it user:tty not user.tty as a username - could have a '.' in it. - -309) Define BSD_COMP for svr4 to get BSD ioctl defs. Also, if we have - sys/sockio.h but SIOCGIFCONF is not defined by including sys/ioctl.h - include sys/sockio.h directly. - -310) Fixed a bug that could cause "sudo -l" to segfault or complain - about non-existent syntax errors. - -Sudo 1.5.7 released. - -311) Fixed square bracket quoting in configure and moved check for -lnsl - to be before -lsocket. - -312) In load_interfaces(), close sock after bwe are done with it. Leak - noticed by Mike Kienenberger . - -313) Missing pieces from change #308; from Mike Kienenberger. - -314) Real Kerberos 5 support from Frank Cusack . - -315) FWTK 'authsrv' support from Kevin Kadow . - -316) Fixed handling and documentation of -with-umask. - -317) If the check for socket() or inet_addr() fails, retry, this time - linking with both -lsocket and -lnsl for those systems that - have interlibrary dependencies. - -Sudo 1.5.8 released. - -318) Add dirfd() macro for systems without it. - -319) Better check for socket() in -lsocket -lnsl in configure. - -320) Minor configure fixes. - -Sudo 1.5.8p1 released. - -321) Fixed a bug wrt quoting characters in command args. - -322) Make --without-sendmail work. - -Sudo 1.5.8p2 released. - -323) Fixed a segv if HOST_IN_LOG defined and gethostbyname() fails. - Reported by Gero Treuner . - -324) Fixed a parse bug wrt the ! operator and runas specs. Noted by - David A Beck . - -325) Use new emalloc/erealloc/estrdup functions (catch errors and exit). - -326) New PAM code that should work on both Solaris and Linux. - -327) Make sudo's usage info better when mutually exclusive args are given - and don't rely on argument order to detect this. From Nick Andrew. - -328) In visudo, shift return value of system() by 8 to get the real exit value. - -Sudo 1.5.9 released. - -329) The runas user and NOPASSWD tags are now persistent across entries - in a command list (ie: cmnd1,cmnd2,cmnd3). A PASSWD tag has been - added to reverse NOPASSWD. The runas user and *PASSWD tags can be - overridden on a per-command basis at which point they become the - new default for the rest of the list. - -330) It is now possible to use the '!' operator in a runas list as - well as in a Cmnd_Alias, Host_Alias and User_Alias. - -331) In estrdup(), do the malloc ourselves so we don't need to rely on the - system strdup(3) which may or may not exist. There is now no need to - provide strdup() for those w/o it. - -332) You can now specify a host list instead of just a host or alias - in a privilege list. Ie: user=host1,host2,ALIAS,!host3 /bin/ls - -333) Stash the "safe" path to the command instead of stashing the struct - stat. Should be safer. - -334) Now set $LOGNAME in addition to $USER. - -335) No longer use stdio in tgetpass() - -336) Don't use _PASSWD_LEN or PASS_MAX as we can't rely on them corresponding - to anything real. Instead, we just use a max password size of 256 - everywhere. - -337) Block keyboard-generated signals during startup and restore signal - mask before exec'ing the program. We don't want the user to be - able to simply kill us and avoid logging. - -338) Rewrote timestamp handling. For the default case, a directory is used - instead of a file. For the tty-based case, the timestamp is just a - file in that directory (eg. /var/run/sudo/username/tty). You now only - get the lecture once, even in the tty case. The goal here is to allow - the tty and non-tty schemes to coexist, though it is worth noting that - when you update a tty file, the mtime of the dir gets updated too. - -339) The meaning of -k has changed to mean "invalidate the timestamp". - There is a new -K option to really remove the timestamp file/dir. - -340) New modular authentication API. This fixes the rat's nest of - #ifdefs that was the old auth code. - -341) New logging functions. log_error() now takes a variable number of - args ala printf() and log_auth() reacts to the return value of validate(). - -342) If a user is not in the sudoers file they are still asked for a password. - This keeps someone who finds a user logged in to a terminal from being - able to tell whether or not the user is allowed to use sudo. - -343) New PAM code again, this time it should be correct. - -344) tgetpass() now has a flag to specify whether or not to turn - off echo while reading the password. Used by the new PAM and - fwtk code. - -345) Fixed shadow password dectection on SCO. - -346) Sudo is now available under a BSD/Apache style license. This is - possible because it no longer contains any of the original 1.1 code. - -347) Added configuration info when sudo is run with the -V flag by root. - -348) Change visudo tmp file from /etc/stmp -> /etc/sudoers.tmp since - Solaris uses stmp for shadow temp file. Also rename _PATH_SUDO_SUDOERS - to _PATH_SUDOERS and _PATH_SUDO_STMP to _PATH_SUDOERS_TMP. - -349) Added configure option to set syslog priorities. - -350) Sudo now locks its log file to prevent mangled entries. - -351) Visudo now locks the sudoers temp file instead of bailing when - the temp file already exists. This fixes the problem of stale - temp files but it does *require* that you not try to put the - temp file in a world-writable directory. This shoud not be - an issue as the temp file should live in the same dir as sudoers. - -352) Fixed crypt() check in libufc. - -353) It is now possible to put a list of users as the first thing in a - user specification. I don't suggest this but it makes the grammar - more uniform. - -354) Visudo will now warn about what it thinks are undefined aliases. - Since it can't be 100% sure these are just warnings, not errors. - -355) Add a --without-passwd option to configure that turns off - passwd/shadow file authentication. Only usable with an alternate - authentication scheme. - -356) Add a --disable-authentication option to configure that causes sudo - to not require authentication by default. The PASSWD tag can be - used to require authentication for an entry. - -357) Add a --with-devel option to add -Wall and uncomment yacc/lex - generation in Makefile. - -358) Zero out plaintext password after use (should do encrypted as well). - -359) Added real dependencies in Makefile. - -360) Deprecated --with-otp-only in favor of --without-passwd. - -361) Add --with-mail-if-no-host to send mail if a user tries to run sudo on - a host for which he/she is not authorized. - -362) Most of sudo now runs as root instead of the invoking user to - minimize the possibility of user control via signals or tracing. - -363) Now Support CIDR-style netmasks (ie: 128.138.0.0/16). - -364) In "sudo -l" mode, the type of the stored (expanded) alias was not - stored with the contents. This could lead to incorrect output - if the sudoers file had different alias types with the same name. - Normal parsing (ie: not in '-l' mode) is unaffected. - -365) Now include strcasecmp() for those without it. - -366) Most compile-time options are now changable at runtime via - the 'Defaults' specification in the sudoers file. - -367) Added a -L flag to printout all the possible 'Defaults' parameters. - -368) It is now possible to escape "special" characters in usernames, hostnames, - etc with a backslash. - -369) Sudo will now accept a hostname/username/netgroupname that contains - almost any character in it. It seems many people want to use '.' - and other non-alphanumerics in usernames. - -370) Fixed the root_sudo option. Sudo was always complaining that root - was not allowed to run sudo if the root_sudo flag was turned off. - -371) tgetpass() now uses a function to read up until the end of line. - Fixes problems in a pipeline when a program sets the tty mode - to be character at a time. - -372) sudo now turns off core dumps via setrlimit (probably paranoia). - -Sudo 1.6 released. - -373) Better diagnostics on PAM failure. - -374) Killed shell_noargs option, it cannot work since the command needs to - be set before sudoers is parsed. - -375) Fixed the following Defaults options: set_home, fqdn, syslog, tty_tickets, - ticket_dir, insults. - -376) When using select() in tgetpass(), do a separate select before - each read to be sure we can timeout correctly. - -377) SecurID support compiles and works again. - -378) Fixed a bug parsing runas modifiers. If a user spec contained multiple - runas specs, the latter ones may not be applied. - -379) #uid now works in a RunasAlias - -380) Don't ask the user for a password if the user is not allowed to run - the command and the authenticate flag (in sudoers) is false. - -381) Added configure check for initgroups(3). - -382) Use our own fnmatch() if there is no fnmatch.h, even if there is an - fnmatch() in libc. - -Sudo 1.6.1 released. - -383) Better behavior for -l and -v flags in conjunction with NOPASSWD and - added "verifypw" and "listpw" options. - -384) For HP-UX with cc, add the -Aa flag along with -D_HPUX_SOURCE. - -385) Fix compilation with K&R compilers. - -386) For netgroup host matching, match against the short version of the - hostname as well as the long one if they are different. - -387) Terminate passwd reading on '\r' in addition to '\n' - -388) Visudo used to loop endlessly if a user entered ^D at the whatnow - prompt. EOF is now treaded as 'x' (exit w/o saving changes). - -389) The 'shell_noargs' runtime option is back based on a patch from - bguillory@email.com. - -390) Systems that return RLIM_INFINITY for RLIMIT_NOFILE (like AIX) - would loop for a very loing time during sudo startup. A value of - RLIM_INFINITY is now ignored (getdtablesize/sysconf is used instead). - -391) Locking in visudo was broken. We now lock the sudoers file, not the - sudoers temp file, which should be safe. - -392) PAM fixups: custom prompts now work correctly and errors are - dealt with more sanely. Patches from Cloyce D. Spradling. - -Sudo 1.6.2 released. - -393) Users in the 'exempt' group shouldn't get their $PATH overridden - by 'secure-path'. Patch from jmknoble@pobox.com. - -394) Pam now works on HP-UX 11.0, thanks to Jeff A. Earickson. - -395) Fixed a bug that caused an infinite loop when the password - timeout was disabled. - -396) It is now possible to set the path to the editor for visudo as well - as the flag that determines whether or not visudo will look at - $EDITOR in the sudoers file. - -397) configure now pulls in the values of LIBS, LDFLAGS, CPPFLAGS, etc - as the documentation says it ought to. - -398) Added rootpw, runaspw, and targetpw to prompt for the root, runas_default - and target user's passwords respectively (instead of the invoking user's - password). - -399) Added -S flag to force password read from stdin. - -400) Restore coredumpsize resource limit before exec'ing the child - process (sudo sets it to 0 internally). - -401) Truncate unencrypted password to 8 chars if encrypted password is exactly - 13 characters (indicateing standard a DES password). Many versions - of crypt() do this for you, but not all (like HP-UX's). - -402) Fixed a typo/thinko that broke secureware support for long passwords. - -403) Added a new command line switch '-c' to support BSD login classes. - The '-c' option can be used to sudo a command with specific resource - limits in the login.conf database. This feature is optionally enabled - via the --with-logincap configure switch. Based on a patch from - Michael D. Marchionna. - -404) Fixed a bug where sudo would hang around and consume CPU if we spawn - a long-running process. - -405) Deal with HP-UX password aging info tacked on to the end of the - encrypted password. - -406) Added set_logname run-time option. When unset, sudo will not set - the USER and LOGNAME environment variables. - -407) Wildcards are now allowed in the hostnames specified in sudoers. - The 'fqdn' option is often required for this to be useful. - -408) Fixed a bug where host and user qualifiers in a Defaults entry were - not being used correctly and the entry was being applied globally. - -Sudo 1.6.3 released. - -409) Fixed targetpw, rootpw, and runaspw options when used with non-passwd - authentication (pam, etc). - -Sudo 1.6.3p1 released. - -410) When the targetpw flag is set, use the target username as part - of the timestamp path. - -Sudo 1.6.3p2 released. - -411) Fixed a bug that prevented the -H option from being useful. - -Sudo 1.6.3p3 released. - -412) Fixed a case where a string was used after it had been freed. - -Sudo 1.6.3p4 released. - -413) Fixed listpw and verifypw sudoers options. - -414) Do not write NUL when writing passwd prompt; hag@linnaean.org. - -Sudo 1.6.3p5 released. - -415) Fix word splitting bug that caused a segv for very long command line args. - -Sudo 1.6.3p6 released. - -416) Fix negation of path-type Defaults entries in a boolean context. - -Sudo 1.6.3p7 released. - -417) Visudo now checks for the existence of an editor and gives a sensible - error if it does not exist. - -418) The path to the editor for visudo is now a colon-separated list of - allowable editors. If the user has $EDITOR set and it matches - one of the allowed editors that editor will be used. If not, - the first editor that actually exists is used. - -419) Visudo now does its own fork/exec instead of calling system(3). - -420) Allow special characters (including '#') to be embedded in pathnames - if quoted by a '\\'. The quoted chars will be dealt with by fnmatch(). - Unfortunately, 'sudo -l' still prints the '\\'. - -421) Added the always_set_home option. - -422) Strip NLSPATH and PATH_LOCALE out from the environment to prevent - reading of protected files by a less privileged user. - -423) Added support for BSD authentication and associated -a flag. - -424) Added check for _innetgr(3) since NCR systems have this instead - of innetgr(3). - -425) Added stay_setuid option for systems that have libraries that perform - extra paranoia checks in system libraries for setuid programs. - -426) Environment munging is now done by hand. The environment is zeroed - upon sudo startup and a new environment is built before the command - is executed. This means we don't rely on getenv(3), putenv(3), - or setenv(3). - -427) Added a class of environment variables that are only cleared if they - contain '/' or '%' characters. - -428) Use stashed user_gid when checking against exempt gid since sudo - sets its gid to SUDOERS_GID, making getgid() return that, not the - real gid. Fixes problem with setting exempt group == SUDOERS_GID. - Fix from Paul Kranenburg. - -429) Fixed file locking in visudo on NeXT which has a broken lockf(). - Patch from twetzel@gwdg.de. - -430) Regenerated configure script with autoconf-2.52 (required some - tweaking of configure.in and friends). - -431) Added mail_badpass option to send mail when the user does not - authenticate successfully. - -432) Added env_reset Defaults option to reset the environment to - a clean slate. Also implemented env_keep Defaults option - to specify variables to be preserved when resetting the - environment. - -433) Added env_check and env_delete Defaults options to allow the admin - to modify the built-in list of environment variables to remove. - -434) If timestamp_timeout < 0 then the timestamp never expires. This - allows users to manage their own timestamps and create or delete - them via 'sudo -v' and 'sudo -k' respectively. - -435) Authentication routines that use sudo's tgetpass() now accept - ^C or ^Z at the password prompt and sudo will act appropriately. - -436) Added a check-only mode to visudo to check an existing sudoers - file for sanity. - -437) Visudo can now edit an alternate sudoers file. - -438) If sudo is configured with S/Key support and the system has - skeyaccess(3) use that to determine whether or not to allow - a normal Unix password or just S/Key. - -439) Fixed CIDR handling in sudoers. - -440) Fixed a segv if the local hostname is not resolvable and - the 'fqdn' option is set. - -441) "listpw=never" was not having an effect for users who did not - appear in sudoers--now it does. - -442) The --without-sendmail option now works on systems with - a /usr/include/paths.h file that defines _PATH_SENDMAIL. - -443) Removed the "secure_path" Defaults option as it does not work and - cannot work until the parser is overhauled. - -444) Added new -P flag and "preserve_groups" sudoers option to cause - sudo to preserve the group vector instead of setting it to that - of the target user. Previously, if the target user was root - the group vector was not changed. Now it is always changed unless - the -P flag or "preserve_groups" option was given. - -445) If find_path() fails as root, try again as the invoking user (useful - for NFS). Idea from Chip Capelik. - -446) Use setpwent()/endpwent() and its shadow equivalents to be sure - the passwd/shadow file gets closed. - -447) Use getifaddrs(3) to get the list of network interfaces if it is - available. - -448) Dump list of local IP addresses and environment variables to clear - when 'sudo -V' is run as root. - -449) Reorganized the lexer a bit and added more states. Sudo now does a - better job of parsing command arguments in the sudoers file. - -450) Wrap each call to syslog() with openlog()/closelog() since some - things (such as PAM) may call closelog(3) behind sudo's back. - -451) The LOGNAME and USER environment variables are now set if the user - specified a target uid and that uid exists in the password database. - -452) configure will no longer add the -g flag to CFLAGS by default. - -453) Now call pam_setcreds() to setup creds for the target user when - PAM is in use. On Linux this often sets resource limits. - -454) If "make install" is run by non-root and the destination dir - is writable, install things normally but don't set owner and mode. - -455) The Makefile now supports installing in a shadow hierarchy - specified via the DESTDIR variable. - -456) config.h.in is now generated by autoheader. - -Sudo 1.6.4 released. - -457) Move the call to rebuild_env() until after MODE_RESET_HOME is set. - Otherwise, the set_home option has no effect. - -458) Fix use of freed memory when the "fqdn" flag is set. This was - introduced by the fix for the "segv when gethostbynam() fails" bug. - -459) Add 'continue' statements to optimize the switch statement. - From Solar Designer. - -Sudo 1.6.4p1 released. - -460) Some special characters were not being escaped properly (e.g. '\,') - in command line arguments and would cause a syntax error instead. - -461) "sudo -l" would not work if the always_set_home option was set. - -462) Added a configure option to disable use of POSIX saved IDs for - operating systems where these are broken. - -463) The SHELL environment variable was preserved from the user's environment - instead of being reset based on the passwd database even when the - "env_reset" option was set. - -Sudo 1.6.4p2 released. - -464) Added a configure option to cause mail sent by sudo to be run as - the invoking user instead of root. Some people consider this to - be safer. - -465) If the mailer is being run as root, use a hard-coded environment - that is not influenced in any way by the invoking user's environment. - -466) Fixed the call to skeyaccess(). Patch from Phillip E. Lobbes. - -Sudo 1.6.5 released. - -467) Visudo could access memory that was already freed. - -468) If the skey.access file denied use of plaintext passwords sudo - would exit instead of allowing the user to enter an S/Key. - -Sudo 1.6.5p1 released. - -469) Older versions of BSDi have getifaddrs() but no freeifaddrs(). - -470) BSDi has a fake setreuid() as do certain versions of FreeBSD and NetBSD. - -471) Ignore the return value of pam_setcred(). In Linux-PAM 0.75, - pam_setcred() will return PAM_PERM_DENIED even if the setcred function - of the module succeeds when pam_authenticate() has not been called. - -472) Avoid giving PAM a NULL password response, use the empty string instead. - This avoids a log warning when the user hits ^C at the password prompt - when Linux-PAM is in use. This also prevents older versions of - Linux-PAM from dereferencing the NULL pointer. - -473) The user's password was not zeroed after use when AIX authentication, - BSD authentication, FWTK or PAM was in use. - -Sudo 1.6.5p2 released. - -474) Fixed compilation problem on HP-UX 9.x. - -475) Moved call to endpwent() and added a call to endgrent(). - -476) Fixed a warning conflicting declaration of VOID with AFS. - -477) Fixed a security hole in prompt rewriting found by Global InterSec. - -Sudo 1.6.6 released. - -478) Wildcards now work correctly in the env_keep Defaults directive. - -479) Added support for non-root timestamp dirs. This allows the timestamp - dir to be shared via NFS (though this is not recommended). - -480) Removed double printing of bad environment variable table in -V mode. - -481) configure script has been regenerated with autoconf 2.5.7. - This required some changes to configure.in. - -482) Fixed a compilation problem on SunOS; thanks to Alek O. Komarnitsky. - -483) SecurID 5.0 API support from Michael Stroucken. - -484) Restore state of signal handlers to what we had upon startup. - Fixes a problem when using sudo with nohup; thanks to Paul Markham. - -485) Revamp set_perms() to use setresuid() or setreuid() when available - in preference to POSIX stuff since they allow us to properly - implement "stay_setuid" whereas POSIX does not really. - -486) In strict mode sudo did not throw an error for undefined User_Aliases. - -487) Fixed a Makefile bug on IRIX. - -488) Write the prompt *after* turning off echo to avoid some password - characters being echoed on heavily-loaded machines with fast typists. - -489) Added %U and %H escapes in the prompt and fixed treatment of %%. - -490) Visudo will now add a final newline to sudoers if the user's editor - not add one before EOF. - -491) The lexer state is now reset to its initial value on EOF. - Previously, the state was not reset between parser invocations - which could cause problems for visudo in rare cases. - -492) Added support for Defaults that apply based on the RunasUser. - -493) Sudo now includes copies of strlc{at,py} and uses them throughout. - -494) Sudo is now careful to avoid interger overflow when allocating - memory. This is one of those "should not happen" situations. - -495) Added a configure option (--with-stow) to make sudo compatible - with GNU stow. - -496) auth/kerb5.c now compiles under Heimdal. - -497) The volatile prefix is used in the hopes of preventing compilers - from optimizing away memory zeroing. Unfortunately, this results - in some warnings from gcc. - -498) Better Kerberos IV/V support in the configure script. - -499) Fixed a logic thinko in the SIGCHLD handler that caused problems - with rlogin on HP-UX. - -500) configure now adds -R to LDFLAGS when it adds -L for Solaris and - SVR4. There is a configure option, --with-rpath, to control this. - -501) On AIX, configure will pass extra directory paths to the linker - via the -blibpath ld option. This is only active when additional - library paths are used. It may be disabled via the - --without-blibpath configure option. - -502) The --with-skey and --with-opie configure options now take - an optional directory argument that should have an include and - lib dir for the skey/opie include file and library respectively. - -Sudo 1.6.7 released. - -503) Fixed false positives in the overflow detection of expand_prompt(). - -Sudo 1.6.7p1 released. - -504) An unterminated comment broke Kerberos V authentication. - -505) The krb5-config script is used to determine Kerberos V CPPFLAGS - and LDFLAGS/LIBS if it exists. - -506) Backed out changes to mkinstalldirs from autoconf 2.57 that - caused problems on Tru64 Unix. - -Sudo 1.6.7p2 released. - -507) Kerberos V support should work on latest MIT Kerberos V and Heimdal. - -Sudo 1.6.7p3 released. - -508) Fixed remaining Kerberos V issues with MIT Kerberos V and old Heimdal. - -Sudo 1.6.7p4 released. - -509) Fixed a typo that caused a compilation error on Heimdal. - -510) Darwin (MacOS X) doesn't have a real setreuid() system call. - -511) Fixed a problem with large numbers of environment variables. - -Sudo 1.6.7p5 released. - -512) Fixed a problem on FreeBSD when the user is only listed in NIS (not - master.passwd) and netgroups are used in the master.passwd file. - -513) BSD-style warn/err functions are now used throughout. - -514) Fixed the --with-stow configure option - -515) Added a "sudo_lecture" option that points to a file containing a custom - lecture. - -516) The username in a log entry is no longer truncated at 8 characters. - -517) A new tag, NOEXEC, will prevent a dynamically-linked program being run - by sudo from executing another program (think shell escapes). - Because this uses LD_PRELOAD it has no effect on static binaries. - Idea from Reznic Valery. - -518) TIS fwtk authentication now supports fwtk 2.0 and higher. - -519) Sudo will now try to stat the command to be run as the user - specified by the -u flag if the stat fails as root. Fixes - an NFS issue. - -520) Added Stan Lee / Uncle Ben quote to the lecture (from RedHat). - -521) Added a -i option to simulate an initial login similar to "su -". - Originally based on a patch from David J. MacKenzie. - -522) Added a -e option to edit files the with uid of the invoking user. - This prevents the user from editing other files or running commands - as the target user. If sudo is run as "sudoedit" the -e flag is implied. - -523) If sudo is used to run as root shell, further sudo commands will - be logged as run by the user specified by the SUDO_USER environment - variable. In -e mode (sudoedit), SUDO_USER is used to determine - what user to run the editor when the real uid is 0. - -524) Merged in LDAP support from Aaron Spangler. - -525) Added the --with-pc-insults configure to replace politically - incorrect insults with ones from Alek O. Komarnitsky. - -526) Added start_tls support from Gudleik Rasch . - -527) A uid specified in sudoers now matches the user specified by the - -u flag even if the -u flag specified a name, not a uid. - -528) /tmp/.odus is no longer used for timestamps by default. One of - /var/run/sudo, /var/adm/sudo or /usr/adm/sudo is used depending - on what directories exist. - -529) Quoting globbing characters with a backslash now works as documented. - -530) A negated user/uid in a runas list was not treated the same as a - negated command (it did not override a previously allowed entry). - Now it does. - -531) Added support for Tandem NSK and other systems w/o seteuid(). - -532) The timeout on password reading is now done via alarm(), not select(). - -533) Fixed several issues when closing all open descriptors. Sudo now uses - closefrom() if it exists, using /proc/$$/fd if possible. - -534) Use PATH_MAX, not MAXPATHLEN since the former is standardized. - -535) Added a check in visudo for runas_default being used before it - was set. - -536) If the target user == invoking user a password is no longer required. - -537) PAM support now uses Use pam_acct_mgmt() to check for disabled accounts - (from Brian Farrell). - -538) The sudoers file is now parsed as the runas user in all cases instead - of root. This fixes some issues with running NFS-mounted commands. - -539) Sudo now produces a sensible error message when the targetpw - Defaults option is set and a non-existent uid is specified via -u. - -Sudo 1.6.8 released. - -540) Now find the command base and fill in struct stat earlier. - -541) sudoedit now re-opens the temp file as the invoking user. - -542) struct timespec is used throughout the code base. - -543) Added --with-ldap-conf-file option to override /etc/ldap.conf - -544) Added SSL tls_* certificate checking options when using LDAP. - -545) Sudoedit will now only attempt to edit regular files or links. - -546) Sudo now uses futime() or futimes() where possible. - -547) Updated sample.pam to a current version. - -548) Better detection of unchanged files in sudoedit. - -Sudo 1.6.8p1 released. - -549) Bash exported functions are now stripped from the environment passed - to the program to be executed. - -Sudo 1.6.8p2 released. - -550) The CDPATH variable is now stripped from the environment passed - to the program to be executed. - -551) Fix temp file generation on systems where the _PATH_VARTMP macro - lacks a trailing slash. - -Sudo 1.6.8p3 released. - -552) The KRB5CCNAME environment variable is preserved during sudo - execution for password lookups that use GSSAPI. - -Sudo 1.6.8p4 released. - -553) Added a configure check for systems with a 2-argument version of - timespecsub (like BSD/OS). - -554) Added stub struct defintions to sudo.h to quiet compiler warnings - on some systems. - -555) In sudoers Defaults lines, tuples like "lecture" may now be used - without a value, restoring their old boolean-like nature. - -556) Invalid values for a tuple are now handled correctly. - -Sudo 1.6.8p5 released. - -557) Added a set of missing braces needed for MacOS X / Darwin. - -558) Define LDAP_OPT_SUCCESS for those without it. - -Sudo 1.6.8p6 released. - -559) Warn if the user tries to use the -u option when not running a command. - -560) Better PAM error handling and messages. - -561) Fixed setting of $USER when env_reset is enabled. - -Sudo 1.6.8p7 released. - -562) Fixed noexec functionality on Linux. - -563) Fixed minor format string mismatches in some error cases. - -564) Fixed a bug that prevented Heimdal authentication from working. - -Sudo 1.6.8p8 released. - -565) Updated config.guess and config.sub entries for OpenBSD. - -566) A sudoers entry with sudo ALL no longer overwrites the value of - safe_cmnd. - -Sudo 1.6.8p9 released. - -567) Added PS4 and SHELLOPTS to the list of variables to remove from - the environment. - -Sudo 1.6.8p10 released. - -567) Added JAVA_TOOL_OPTIONS to the list of variables to remove from - the environment. - -Sudo 1.6.8p11 released. - -567) Added PERLLIB, PERL5LIB and PERL5OPT to the list of variables to - remove from the environment. - -Sudo 1.6.8p12 released. - -568) Fixed a file descriptor leak when the lecture file option is enabled. - -569) Added to the list of variables to remove from the environment. - -570) Fixed a Kerberos V security issue that could allow a - user to authenticate using a fake KDC. - -571) Pulled in updated configure and libtool from sudo 1.7. - -572) PAM is now the default on systems where it is supported. - -573) Removed POSIX saved uid use; the stay_setuid option now - requires the setreuid() or setresuid() functions to work. - -574) Regenerated configure with up to date autoconf and libtool. - -575) Fixed fd leak when lecture file option is enabled. - -576) Removed used of POSIX saved uids. The stay_setuid - option now requires setreuid() or setresuid(). - -577) PAM fixes. If the user enters ^C at the password prompt, - abort instead of trying to authenticate with an empty password - (which causes an annoying delay). Also Call pam_open_session() - and pam_close_session() to give pam_limits a chance to run. - -578) Security fix for Kerberos5. If we cannot get a valid service - key using the default keytab it is a fatal error. Now uses - krb5_verify_user() and krb5_init_secure_context() if they - are available. - -579) Fixed securid5 authentication. - -580) Added fcntl F_CLOSEM support to closefrom(). - -581) Added NOEXEC support for AIX 5.3. - -582) Sudo now uses the supplemental group vector for matching. - This fixes problems with split group lines in /etc/group - as well as multiple group sources in nsswitch.conf. - -583) Added more environment variables to remove by default. - -584) Mail from sudo now includes an Auto-Submitted: auto-generated - header ala rfc 3834. - -585) Reworked the environment handling code. - -586) Remove the --with-execv option, it was not useful. - -587) Use TCSADRAIN instead of TCSAFLUSH in tgetpass() since - some OSes have issues with TCSAFLUSH. - -588) Use glob(3) instead of fnmatch(3) for matching pathnames - and stat() each result that matches the basename of the user's - command. This makes "cd /usr/bin ; sudo ./blah" work when - sudoers allows /usr/bin/blah. - -589) Reworked the syslog long line splitting code based on changes - from Eygene Ryabinkin. - -590) Sudo can now with deal more than 32 network interfaces on - Solaris. - -591) Visudo will now honor command line arguments in the EDITOR or - VISUAL environment variables if env_editor is enabled. - -592) LDAP now honors rootbinddn, timelimit and bind_timelimit in - /etc/ldap.conf. - -593) For LDAP, do a sub tree search instead of a base search (one - level in the tree only) for sudo right objects. This allows - system administrators to categorize the rights in a tree to - make them easier to manage. - -594) The env_reset option is now enabled by default. Commands run - through sudo now receive a minimal environment with certain - variables passed through and/or checked. The list of variables - allowed is configurable via the env_keep and env_check options - in sudoers. - -595) Added support for Solaris 10 resource control limits using - the "project" interface. - -596) Moved LDAP schema data into separate files. - -597) Sudo no longer assumes that gr_mem in struct group is non-NULL. - -598) Added support for setting environment variables on the command - line if the command has the SETENV attribute set in sudoers. - -599) Added a -E flag to preserve the environment if the SETENV attribute - has been set. - -600) The sudoers2ldif script now parses Runas users. - -601) The -- flag now behaves as documented. - -602) sudo -k/-K no longer cares if the timestamp is in the future. - -603) When searching for the command, sudo now uses the effective gid - of the runas user. - -604) Sudo no longer updates the timestamp if not validated by sudoers. - -605) Now rebuild environment regardless of how sudo was invoked. - -606) More accurate usage() when called as sudoedit. - -607) Command line environment variables are now treated like - normal environment variables unless the SETENV tag is set. - -608) Better explanation of environment handling in the sudo man page. - -Sudo 1.6.9 released. - -609) Worked around a bug ins some PAM implementations that caused a crash - when no tty was present. - -610) Fixed a crash on some platforms in the error logging function. - -611) Documentation improvements. - -Sudo 1.6.9p1 released. - -612) Fixed updating of the saved environment when the environ pointer - gets changed out from underneath us. - -Sudo 1.6.9p2 released. - -613) Fixed a bug related to supplemental group matching introduced - in 1.6.9. - -Sudo 1.6.9p3 released. - -614) Added IPv6 support from YOSHIFUJI Hideaki. - -615) Fixed sudo_noexec installation path. - -616) Fixed a K&R compilation error. - -Sudo 1.6.9p4 released. - -617) Fixed a bug in the IP address matching introduced by the IPV6 merge. - -618) For "visudo -f file" we now use the permissions of the original file - and not the hard-coded sudoers owner/group/mode. This makes - it possible to use visudo with a revision control system. - -619) Fixed sudoedit when used on a non-existent file. - -620) Regenerated configure using autoconf 2.6.1 and libtool 1.5.24. - -621) Groups and netgroups are now valid in an LDAP sudoRunas statement. - -Sudo 1.6.9p5 released. - -622) Worked around bugs in the session support of some PAM implementations. - The full tty path is now passed to PAM as well. - -623) Sudo now only prints the password prompt if the process is in the - foreground. - -624) inttypes.h is now included when appropriate if it is present. - -625) Simplified alias allocation in the parser. - -Sudo 1.6.9p6 released. - -626) Go back to using TCSAFLUSH instead of TCSADRAIN when turning - off echo in tgetpass(). - -627) Fixed addition of -lutil for logincap on FreeBSD and NetBSD. - -628) Add configure check for struct in6_addr since some systems define - AF_INET6 but have no real IPv6 support. - -Sudo 1.6.9p7 released. - -629) Fixed a bug where a sudoers entry with no runas user specified - was treated differently from a line with the default runas - user specified. - -Sudo 1.6.9p8 released. - -630) The ALL command in sudoers now implies SETENV permissions. - -631) The command search is now performed using the target user's - auxiliary group vector too. - -632) When determining if the PAM prompt is the default "Password: ", - compare the localized version if possible. - -633) Added passprompt_override flag to sudoers to cause sudo's prompt - to be used in all cases. Also set when the -p flag is used. - -Sudo 1.6.9p9 released. - -634) Moved LDAP options into a table for simplified parsing/setting. - -635) Fixed a problem with how some LDAP options were being applied. - -636) Added support for connecting directly to LDAP servers via SSL - in addition to the existing start_tls support. - -Sudo 1.6.9p10 released. - -637) Fixed a compilation problem on SCO related to how they - store the high resolution timestamps in struct stat. - -638) Avoid checking the passwd file group multiple times - in the LDAP query when the user's passwd group is also - listed in the supplemental group vector. - -639) The URI specifier can now be used in ldap.conf even when - the LDAP SDK doesn't support ldap_initialize(). - -640) New %p prompt escape that expands to the user whose password - is being prompted, as specified by the rootpw, targetpw and - runaspw sudoers flags. Based on a diff from Patrick Schoenfeld. - -Sudo 1.6.9p11 released. - -641) Added a configure check for the ber_set_option() function. - -642) Fixed a compilation problem with the HP-UX K&R C compiler. - -643) Revamped the Kerberos 5 ticket verification code. - -644) Added support for the checkpeer ldap.conf variable for - netscape-based LDAP SDKs. - -645) Fixed a problem where an incomplete password could be echoed - to the screen if there was a read timeout. - -Sudo 1.6.9p12 released. - -646) Sudo will now set the nproc resource limit to unlimited on Linux - systems to work around Linux's setuid() resource limit semantics. - On PAM systems the resource limits will be reset by pam_limits.so - before the command is executed. - -647) SELinux support that can be used to implement role based access - control (RBAC). A role and (optional) type may be specified - in sudoers or on the command line. These are then used in the - security context that the command is run as. - -648) Fixed a Kerberos 5 compilation problem with MIT Kerberos. - -Sudo 1.6.9p13 released. - -649) Fixed an invalid assumption in the PAM conversation function - introduced in version 1.6.9p9. The conversation function may - be called for non-password reading purposes as well. - -650) Fixed freeing an uninitialized pointer in -l mode, introduced in - version 1.6.9p13. - -651) Check /etc/sudoers after LDAP even if the user was found in LDAP. - This allows Defaults options in /etc/sudoers to take effect. - -652) Add missing checks for enforcing mode in SELinux RBAC mode. - -Sudo 1.6.9p14 released. - -653) Fixed installation of sudo_noexec.so on AIX. - -654) Updated libtool to version 1.5.26. - -655) Fixed printing of default SELinux role and type in -V mode. - -656) The HOME environment variable is once again preserved by default, - as per the documentation. - -Sudo 1.6.9p15 released. - -657) There was a missing space before the ldap libraries in the Makefile - for some configurations. - -658) LDAPS_PORT may not be defined on older Solaris LDAP SDKs. - -659) If the LDAP server could not be contacted and the user was not present - in sudoers, a syntax error in sudoers was incorrectly reported. - -Sudo 1.6.9p16 released. - -660) The -i flag should imply resetting the environment, as it did in - sudo version prior to 1.6.9. Also, the -i and -E flags are - mutually exclusive. - -661) Fixed the configure test for dirfd() under Linux. - -662) Fixed test for whether -lintl is required to link. - -663) Changed how sudo handles the child process when sending mail. - This fixes a problem on Linux with the mail_always option. - -664) Fixed a problem with line continuation characters inside of - quoted strings. - -Sudo 1.6.9p17 released. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..63023fc --- /dev/null +++ b/ChangeLog @@ -0,0 +1,19639 @@ +2008-12-14 17:40 millert + + * TODO: sync + +2008-12-09 18:48 millert + + * auth/pam.c: Return PAM_AUTH_ERR instead of PAM_CONV_ERR if user + enters ^C at the password prompt. + +2008-12-09 16:13 millert + + * configure.in, configure: Don't try to build sudo_noexec.so on + HP-UX with the bundled compiler as it cannot generate shared + objects. + +2008-12-09 15:55 millert + + * glob.c, lbuf.c, tgetpass.c, emul/charclass.h: K&R compilation + fixes + +2008-12-09 08:49 millert + + * parse.c: Use tq_foreach_fwd when checking pseudo-commands to make + it clear that we are not short-circuiting on last match. When + pwcheck is 'all', initialize nopass to TRUE and override it with + the first non-TRUE entry. + +2008-12-08 10:02 millert + + * parse.c: Do not short circuit pseudo commands when we get a match + since, depending on the settings, we may need to examine all + commands for tags. + +2008-12-03 15:58 millert + + * sudoers.cat, sudoers.man.in: regen + +2008-12-03 15:57 millert + + * sudoers.pod: hostnames may also contain wildcards + +2008-12-03 15:40 millert + + * Makefile.in: remove stamp-* files and linux core files in clean + target + +2008-12-02 12:30 millert + + * config.h.in, configure, configure.in, auth/sudo_auth.h: Use + HAVE_SIA_SES_INIT instead of HAVE_SIA for Digital UNIX + +2008-11-26 15:10 millert + + * configure, configure.in: correctly enable SIA on Digital UNIX + +2008-11-25 20:06 millert + + * TODO: checkpoint + +2008-11-25 20:05 millert + + * ChangeLog: sync + +2008-11-25 12:01 millert + + * check.c, sudo.h, tgetpass.c: Even if neither stdin nor stdout are + ttys we may still have /dev/tty available to us. + +2008-11-24 10:09 millert + + * sudoers.cat, sudoers.man.in: regen + +2008-11-24 10:08 millert + + * sudoers.pod: fix typos; Markus Lude + +2008-11-24 07:08 millert + + * ChangeLog: sync + +2008-11-23 19:42 millert + + * toke.c: regen + +2008-11-23 19:41 millert + + * toke.l: Fix matching of a line that only consists of a comment + char + +2008-11-22 13:17 millert + + * auth/pam.c: MacOS pam will retry conversation function if it + fails so just treat ^C as an empty password. + +2008-11-22 10:12 millert + + * visudo.c: When checking for alias use, also check defaults + bindings. + +2008-11-22 10:01 millert + + * redblack.c: unused var + +2008-11-22 09:42 millert + + * redblack.c: Replace my rbdelete with Emin's version (which + actually works ;-) + +2008-11-19 12:01 millert + + * testsudoers.c: malloc debugging + +2008-11-19 07:37 millert + + * visudo.c: malloc options in devel mode for visudo too + +2008-11-18 10:57 millert + + * sudo.c: fix compilation on non-C99; from Theo + +2008-11-18 10:50 millert + + * visudo.c: fix check_aliases + +2008-11-18 08:29 millert + + * alias.c: when destroying an alias, free the correct data pointer + +2008-11-18 07:54 millert + + * auth/sudo_auth.h: add proto for aixauth_cleanup; from Dale King + +2008-11-15 13:34 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat, + visudo.man.in: regen + +2008-11-15 13:34 millert + + * sudo.pod, sudoers.pod, visudo.pod: standardize on the term + 'option' for command line options (not flag) + +2008-11-14 06:18 millert + + * INSTALL: Add note on configuring HP-UX pam + +2008-11-11 13:28 millert + + * check.c, sudo.c: Move tty checks into check_user() so we only do + them if we actually need a password. + +2008-11-11 12:34 millert + + * sudo.c: Don't error out if no tty or askpass unless we actually + need to authenticate. + +2008-11-10 15:20 millert + + * ChangeLog: regen + +2008-11-10 08:07 millert + + * pathnames.h.in, sudo.c: s/overriden/overridden/; from Tobias + Stoeckmann + +2008-11-09 15:18 millert + + * visudo.c, WHATSNEW: check sudoers owner and mode in strict mode + +2008-11-09 09:15 millert + + * gram.c, toke.c: regen + +2008-11-09 09:13 millert + + * alias.c, alloc.c, closefrom.c, compat.h, defaults.c, defaults.h, + env.c, fileops.c, gettime.c, gram.y, ins_csops.h, insults.h, + interfaces.c, interfaces.h, lbuf.c, license.pod, list.c, + logging.c, logging.h, parse.c, parse.h, pwutil.c, redblack.c, + redblack.h, snprintf.c, sudo.c, sudo.pod, sudo_edit.c, + sudo_nss.h, testsudoers.c, toke.l, tsgetgrpw.c, utimes.c, + version.h, visudo.c, zero_bytes.c, LICENSE, sudoers.pod, + visudo.pod, auth/afs.c, auth/aix_auth.c, auth/bsdauth.c, + auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, auth/pam.c, + auth/securid.c, auth/securid5.c, auth/sia.c, auth/sudo_auth.h, + sudo.man.in, sudoers.man.in, visudo.man.in: Update copyright + years. + +2008-11-09 08:48 millert + + * fnmatch.c, glob.c, emul/charclass.h: add my copyright + +2008-11-08 10:40 millert + + * toke.c, toke.l: The loop in fill_cmnd() was going one byte too + far past the end, resulting in a NUL being written immediately + after the buffer end. + +2008-11-08 10:31 millert + + * UPGRADE, WHATSNEW: add sections on tgetpass changes + +2008-11-08 10:30 millert + + * tgetpass.c: Treat EOF w/o newline as an error. + +2008-11-07 17:42 millert + + * parse.c: Fix "sudo -v" when NOPASSWD is set. + +2008-11-07 12:45 millert + + * auth/: bsdauth.c, fwtk.c, pam.c, sudo_auth.c, sudo_auth.h: No + longer treat an empty password at the prompt as special. To quit + out of sudo you now need to hit ^C at the password prompt. + +2008-11-06 21:07 millert + + * sudoers.cat, sudoers.man.in: regen + +2008-11-06 21:06 millert + + * def_data.c, def_data.h, def_data.in, sudo.c, sudoers.pod: Sudo + will now refuse to run if no tty is present unless the new + visiblepw sudoers flag is set. + +2008-11-05 19:42 millert + + * aix.c: just use RLIM_INFINITY for RLIM_SAVED_MAX if + RLIM_SAVED_MAX not defined + +2008-11-05 19:40 millert + + * aix.c: fix fallback value for RLIM_SAVED_MAX + +2008-11-05 19:14 millert + + * auth/: aix_auth.c, sudo_auth.h: Move clearing of AUTHSTATE into + aixauth_cleanup. + +2008-11-05 19:08 millert + + * env.c, auth/aix_auth.c: Unset AUTHSTATE after calling + authenticate() as it may not be correct for the user we are + running the command as. + +2008-11-05 19:05 millert + + * isblank.c: Add isblank() function for systems without it. Needed + for POSIX character class matching in fnmatch.c and glob.c. + +2008-11-05 11:02 millert + + * TROUBLESHOOTING: expound on sudo and cd + +2008-11-04 15:52 millert + + * ChangeLog: regen + +2008-11-04 15:46 millert + + * sudoers.cat, sudoers.man.in: regen + +2008-11-04 15:45 millert + + * sudoers.pod: mention defauts parse order + +2008-11-03 13:19 millert + + * Makefile.in, aclocal.m4, compat.h, configure: Add isblank() + function for systems without it. Needed for POSIX character + class matching in fnmatch.c and glob.c. + +2008-11-03 12:54 millert + + * Makefile.in: add emul/charclass.h to HDRS + +2008-11-02 14:08 millert + + * TODO: checkpoint + +2008-11-02 14:06 millert + + * parse.c, defaults.c, testsudoers.c, visudo.c: Move + update_defaults into defaults.c and call it properly from visudo + and testsudoers. + +2008-11-02 09:51 millert + + * defaults.c, interfaces.c, pwutil.c, sudo.c, sudo_edit.c, + tgetpass.c, tsgetgrpw.c: use zero_bytes() instead of memset() for + consistency + +2008-11-02 09:45 millert + + * logging.c, mon_systrace.c, parse.c, sudo.c, sudo_edit.c, + tgetpass.c, visudo.c: Zero out sigaction_t before use in case it + has non-standard entries. + +2008-11-02 09:35 millert + + * match.c: quiet gcc + +2008-11-02 09:28 millert + + * match.c: Short circuit glob() checks if basename(pattern) != + basename(command). Refactor code that checks for a command in a + directory and use it in the glob case if the resolved pattern + ends in a '/'. + +2008-11-01 09:20 millert + + * defaults.h, parse.c, sudo.c, testsudoers.c, visudo.c: Defer + setting runas defaults until after runaspw/gr is setup. + +2008-10-29 13:26 millert + + * match.c, sudo.c, testsudoers.c: Use MAXHOSTNAMELEN+1 when + allocating host/domain name since some systems do not include + space for the NUL in the size. Also manually NUL-terminate + buffer from gethostname() since POSIX is wishy-washy on this. + +2008-10-26 17:13 millert + + * sudo.c, sudoers.pod: When setting the umask, use the union of the + user's umask and the default value set in sudoers so that we + never lower the user's umask when running a command. + +2008-10-26 16:43 millert + + * sudo.c: Don't try to read from a zero-length sudoers file. + Remove the bogus Solaris work-around for EAGAIN. Since we now + use fgetc() it should not be a problem. + +2008-10-25 09:22 millert + + * parse.c: In update_defaults() check the return value of + user*_matches against ALLOW so we don't inadvertantly match on + UNSPEC. + +2008-10-24 09:52 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.ldap.cat, + sudoers.ldap.man.in, sudoers.man.in, visudo.cat, visudo.man.in: + regen man pages; no more hyphenation + +2008-10-24 09:49 millert + + * sudo.c: Don't error out on a zero-length sudoers file. With the + advent of #include the user could create a situation where sudo + is unusable. + +2008-10-23 12:06 millert + + * config.h.in, configure, configure.in, auth/kerb5.c: Newer heimdal + has 2-argument krb5_get_init_creds_opt_free() like MIT krb5. + Really old heimdal has no krb5_get_init_creds_opt_alloc() at all. + Add configure tests to handle all the cases. + +2008-10-08 17:28 millert + + * sudo.pod: resort ENVIRONMENT + +2008-10-08 17:09 millert + + * sudoers.pod: document sudoers_locale + +2008-10-08 16:56 millert + + * sudo.pod, sudo_edit.c: add SUDO_EDITOR variable that sudoedit + uses in preference to VISUAL or EDITOR + +2008-10-08 14:27 millert + + * toke.c, toke.l: In fill_cmnd(), collapse any escaped + sudo-specific characters. Allows character classes to be used in + pathnames. + +2008-10-03 16:02 millert + + * lbuf.c: fix typo in non-C89 function declaration + +2008-10-03 15:56 millert + + * sudoers.pod: Mention POSIX characters classes now that out + fnmatch() and glob() support them. + +2008-10-03 15:55 millert + + * sample.sudoers, sudoers.pod: Replace [A-z] (which won't match in + UTF8) with [A-Za-z] which is locale agnostic. + +2008-10-03 10:02 millert + + * parse.h: use __signed char if we are going to assign a negative + value since on Power, char is unsigned by default + +2008-10-03 09:59 millert + + * configure, configure.in, config.h.in: Add tests for __signed char + and signed char. + +2008-10-03 09:19 millert + + * aix.c: Fix AIX limit setting. getuserattr() returns values in + disk blocks rather than bytes. The default hard stack size in + newer AIX is RLIM_SAVED_MAX. From Dale King. + +2008-09-26 17:13 millert + + * fnmatch.c, glob.c, emul/charclass.h: Add character class support + to included glob(3) and fnmatch(3). + +2008-09-16 08:28 millert + + * emul/fnmatch.h: Remove UCB advertising clause and some + compatibility defines. + +2008-09-14 16:07 millert + + * sudo_edit.c: Check EDITOR/VISUAL to make sure sudoedit is not + re-invoking itself or sudo. This allows one to set EDITOR to + sudoedit without getting into an infinite loop of sudoedit + running itself until the path gets too big. + +2008-09-13 20:45 millert + + * def_data.c, def_data.h, def_data.in, defaults.c, sudo.c: Add + sudoers_locale Defaults option to override the default sudoers + locale of "C". + +2008-09-13 14:09 millert + + * sudo.c: Set locale to system default except for during sudoers + parse. + +2008-09-12 09:34 millert + + * match.c: Redo change in 1.34 to use pointer arithmetic. + +2008-09-11 07:06 millert + + * match.c: Fix a dereference (read) of a freed pointer. Reported + by Patrick Williams. + +2008-08-23 19:09 millert + + * sudo.c: Set locale to "C" to avoid interpretation issues with + character ranges in sudoers. May want to make the locale a + sudoers option in the future. + +2008-08-20 07:45 millert + + * config.h.in: we no longer use setproctitle + +2008-08-20 07:41 millert + + * sudo.h: remove #if 1 + +2008-08-20 07:40 millert + + * LICENSE, mkstemp.c: Use my replacement mkstemp() from the mktemp + package. + +2008-07-12 08:53 millert + + * gram.c: regen with yacc skeleton bug fixed + +2008-07-12 08:48 millert + + * sudoers.pod: Remove duplicate "as root". From Martin Toft. + +2008-07-02 06:27 millert + + * pwutil.c, sudo.c, testsudoers.c, sudo.h: Flesh out the fake + passwd entry used for running commands as a uid not listed in the + passwd database. Fixes an issue with some PAM modules. + +2008-07-01 07:57 millert + + * sudo.c: Error out in -i mode if the user has no shell. This can + happen when running commands as a uid with no password entry. + +2008-06-26 07:49 millert + + * toke.c, toke.l: Better fix for line continuation inside double + quotes. Now accepts whitespace between the backslash and the + newline like the main lexer. + +2008-06-25 14:31 millert + + * toke.c, toke.l: Fix line continuation in strings. It was only + being honored if preceded by whitespace. + +2008-06-22 16:19 millert + + * config.h.in, configure, configure.in, logging.c: Replace the + double fork with a fork + daemonize. + +2008-06-21 14:59 millert + + * env.c, sudo.c: The -i flag should imply env_reset. This got + broken in sudo 1.6.9. + +2008-06-20 20:34 millert + + * logging.c, sudo.c, sudo_edit.c, visudo.c: Change how the mailer + is waited for. Instead of having a SIGCHLD handler, use the + double fork trick to orphan the child that opens the pipe to + sendmail. Fixes a problem running su on some Linux distros. + +2008-06-20 17:16 millert + + * configure, configure.in: Fix configure test for dirfd() on Linux + where DIR is opaque. + +2008-06-17 17:42 millert + + * tgetpass.c: Get rid of the QNX TCSAFLUSH -> TCSADRAIN hack. If + QNX still has this problem we'll need to revisit this again. + +2008-06-10 21:13 millert + + * logging.c: Ignore SIGPIPE instead of blocking it when piping to + the mailer. If we only block the signal it may be delivered + later when we unblock. Also, there is no need to block SIGCHLD + since we no longer do the double fork. The normal SIGCHLD + handler is sufficient. + +2008-06-08 17:37 millert + + * configure, configure.in: Add description for NO_PAM_SESSION, from + a redhat patch. + +2008-06-06 09:36 millert + + * sudo.cat, sudo.man.in, sudo.pod: Fix typos in -i usage + +2008-05-18 13:54 millert + + * configure, configure.in: Redo the test for dgettext() in a way + that hopefully will work around the libintl_dgettext() undefined + problem. + +2008-05-11 09:21 millert + + * schema.ActiveDirectory: change filename in comment + +2008-05-10 09:18 millert + + * Makefile.in, README.LDAP, sudoers.ldap.cat, sudoers.ldap.man.in, + sudoers.ldap.pod: Reference schema.ActiveDirectory + +2008-05-09 14:49 millert + + * schema.OpenLDAP, schema.iPlanet: Mark sudoRunAs as deprecated. + +2008-05-09 14:48 millert + + * schema.ActiveDirectory: add sudoRunAsUser and sudoRunAsGroup + +2008-05-09 14:01 millert + + * schema.ActiveDirectory: Active Directory schema by Chantal + Paradis and Eric Paquet + +2008-05-08 17:54 millert + + * parse.c: remove an XXX that was fixed + +2008-05-08 12:53 millert + + * ChangeLog: sync + +2008-05-08 12:49 millert + + * parse.c: Initialize tags to UNSPEC instead of def_* in "sudo -l" + mode. This fixes a problem where the tag value printed was + influenced by defaults set in the first pass through the parser. + +2008-05-03 21:29 millert + + * Makefile.in, sudo.psf: No point in packaging the TODO file + +2008-05-03 21:24 millert + + * ChangeLog: sync + +2008-05-02 20:53 millert + + * WHATSNEW, def_data.c, def_data.h, def_data.in, env.c, sudo.c, + sudo.h, sudoers.cat, sudoers.man.in, sudoers.pod: Add env_file + Defaults option that is similar to /etc/environment on some + systems. + +2008-05-02 16:38 millert + + * Makefile.in, README, TODO, WHATSNEW, sudo.cat, sudo.man.in, + sudoers.cat, sudoers.ldap.cat, sudoers.ldap.man.in, + sudoers.man.in, version.h, visudo.cat, visudo.man.in: change + version to 1.7.0 + +2008-05-02 16:37 millert + + * UPGRADE: initial valgrind pass done + +2008-04-23 08:30 millert + + * ldap.c: Fix typo/think in sudo_ldap_read_secret() when storing + the secret. + +2008-04-11 10:03 millert + + * ldap.c: define LDAPS_PORT if the system headers do not + +2008-04-10 14:54 millert + + * gram.c, gram.y: Fix another memory leak in init_parser(). + +2008-04-10 12:51 millert + + * configure, configure.in: There was a missing space before the + ldap libs in SUDO_LIBS for some configurations. + +2008-04-10 11:28 millert + + * alias.c, gram.c, gram.y, toke.c, toke.l: Clean up some memory + leaks pointed out by valgrind. + +2008-04-07 14:39 millert + + * sudo.c: fix "sudo -s" broken by mode/flags breakout + +2008-04-07 14:26 millert + + * configure, configure.in: remove duplicate check for dgettext + +2008-04-05 15:54 millert + + * aix.c: Fall back to default stanza if no user-specific limit is + found. + +2008-04-02 15:56 millert + + * snprintf.c: include stdint.h if present + +2008-04-02 15:28 millert + + * snprintf.c: Use LLONG_MAX, not the old QUAD_MAX + +2008-04-01 19:18 millert + + * sudoers.ldap.pod: fix cut and pasto + +2008-03-31 11:24 millert + + * pwutil.c: Add #ifdef PURITY + +2008-03-30 17:36 millert + + * auth/bsdauth.c: remove useless cast + +2008-03-27 19:07 millert + + * ChangeLog: sync + +2008-03-27 19:04 millert + + * TODO: sync + +2008-03-27 19:01 millert + + * sudo.h: Split MODE_* defines into primary and flags. + +2008-03-26 13:11 millert + + * aix.c: It turns out the logic for getting AIX limits is more + convoluted than I realized and differs depending on whether the + soft and/or hard limits are defined. + +2008-03-23 10:18 millert + + * Makefile.in, configure, configure.in: Back out AIX-specific + change to set the sudo_noexec path to the .a file, we do really + want to use the .so file. Since libtool doesn't do that + correctly, just install the .so file ourselves in the Makefile. + +2008-03-23 10:12 millert + + * install-sh: If the file given to install is a path, only use the + basename of the file when building the destination path. + +2008-03-18 16:08 millert + + * sudo.c: parse_args() cleanup: Sort command line options in the + getopt() switch The -U option requires a parameter Normalize a + few ISSET calls Split mode into mode and flags and retire the + now-obsolete excl variable + +2008-03-18 16:04 millert + + * WHATSNEW, check.c, sudo.c, sudo.cat, sudo.h, sudo.man.in, + sudo.pod, sudo_usage.h.in: Add -n (non-interactive) flag. + +2008-03-18 15:59 millert + + * sudo.c: Move version printing, etc. into a separate function. + +2008-03-18 15:57 millert + + * sudo.c: Don't try to cleanup nsswitch if it has not been + initialized. + +2008-03-17 11:09 millert + + * logging.c: Block SIGPIPE in send_mail() so sudo is not killed by + a problem executing the mailer. + +2008-03-14 08:11 millert + + * configure.in, configure: AIX shared libs end in .a, not .so. + +2008-03-13 07:34 millert + + * env.c: Preserve HOME by default too. Matches documentation and + previous behavior. + +2008-03-12 19:42 millert + + * sudo.c: Use getopt() to parse the command line. We need to be + able to intersperse env variables and options yet still honor + "--"" which complicates things slightly. + +2008-03-06 14:46 millert + + * ChangeLog: sync + +2008-03-06 14:43 millert + + * acsite.m4, configure, ltmain.sh: update to libtool-1.5.26 + +2008-03-06 14:32 millert + + * config.guess, config.sub: update from libtool-1.5.26 distribution + +2008-03-06 13:18 millert + + * aix.c, sudo.h: attempt to fix compilation errors on AIX + +2008-03-06 13:08 millert + + * Makefile.in: fix typo in last commit + +2008-03-06 13:07 millert + + * Makefile.in: Add WHATSNEW file to the distribution + +2008-03-06 12:43 millert + + * visudo.c: use warningx instead of fprintf(stderr, ...) + +2008-03-06 12:31 millert + + * list.c: add DEBUG to list2tq + +2008-03-06 12:28 millert + + * ChangeLog, TODO: sync + +2008-03-06 12:21 millert + + * WHATSNEW: mention mailfrom + +2008-03-06 12:19 millert + + * Makefile.in, config.h.in, configure, configure.in, set_perms.c, + sudo.h, aix.c: Add aix_setlimits() to set resource limits on AIX + using a combination of getuserattr() and setrlimit(). Currently + untested. + +2008-03-05 16:52 millert + + * def_data.c, def_data.h, def_data.in, logging.c, sudoers.cat, + sudoers.pod, sudoers.man.in: Add mailfrom Defaults option that + sets the value of the From: field in the warning/error mail. If + unset the login name of the invoking user is used. + +2008-03-05 16:18 millert + + * defaults.c: store a copy of _PATH_SUDO_ASKPASS in def_askpass + that is freeable + +2008-03-05 15:19 millert + + * gram.c, gram.y: When adding a default, only call list2tq() once + to do the list to tq conversion. It is not legal to call list2tq + multiple times on the same list since list2tq consumes and + modifies the list argument. + +2008-03-05 09:38 millert + + * sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod: comment + out XXXs for now + +2008-03-05 09:36 millert + + * WHATSNEW: mention askpass + +2008-03-04 17:20 millert + + * sudo.c: Error out if both -A and -S are specified Error out if -A + is specified but no askpass is configured + +2008-03-04 17:16 millert + + * configure, configure.in: we are not going to ship a sudo-specific + askpass + +2008-03-03 14:30 millert + + * sudo.h: fix definition of TGP_ASKPASS + +2008-03-03 13:54 millert + + * def_data.c, def_data.in: make askpass boolean-capable + +2008-03-03 13:53 millert + + * INSTALL: document --with-askpass + +2008-03-02 19:27 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, + sudoers.ldap.cat, visudo.cat: regen + +2008-03-02 17:31 millert + + * sudo.pod, sudo_usage.h.in, sudoers.pod: document -A and askpass + +2008-03-02 09:31 millert + + * check.c, configure, configure.in, def_data.c, def_data.h, + def_data.in, defaults.c, pathnames.h.in, sudo.c, sudo.h, + sudo_usage.h.in, tgetpass.c, auth/sudo_auth.c: Add support for + running a helper program to read the password when no tty is + present (or when specified with the -A flag). TODO: docs. + +2008-03-02 08:38 millert + + * def_data.c, def_data.in: add missing printf format to SELinux + role and type strings + +2008-02-27 09:26 millert + + * INSTALL, configure, configure.in: Disable use of + gss_krb5_ccache_name() by default and add + --enable-gss-krb5-ccache-name configure option to enable it. It + seems that gss_krb5_ccache_name() doesn't work properly with some + combinations of Heimdal and OpenLDAP. + +2008-02-22 15:33 millert + + * selinux.c: Ignore setexeccon() failing in permissive mode. Also + add a call to setkeycreatecon() (though this is probably + insufficient). From Dan Walsh. + +2008-02-22 15:19 millert + + * auth/pam.c: Only set std_prompt for the PAM_PROMPT_* cases. The + conversation function may be called for non-password reading + purposes so we must be careful not to use def_prompt in cases + where it may not be set. + +2008-02-20 12:00 millert + + * selinux.c: Don't free the new tty context, we need to keep it + around when we restore the tty context after the command + completes + +2008-02-19 16:04 millert + + * selinux.c: s/newrole/sudo/ + +2008-02-19 13:21 millert + + * sudo.man.pl, sudo.pod: Only put login_cap(3) in SEE ALSO section + if we have login.conf support + +2008-02-18 11:05 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.ldap.cat, + sudoers.ldap.man.in, sudoers.man.in, visudo.cat, visudo.man.in: + regen + +2008-02-18 10:53 millert + + * Makefile.in, configure, configure.in, sudo.man.pl, sudo.pod, + sudoers.man.pl, sudoers.pod: Substitute in comment characters for + lines partaining to login.conf, BSD auth and SELinux and only + enable them if pertinent. + +2008-02-18 10:42 millert + + * Makefile.in, sudo.pod, sudoers.ldap.pod, sudoers.pod, visudo.pod: + Remove the =cut on the first line (above the copyright notice) to + quiet pod2man. Also remove the hackery in the FILES section and + just deal with the fact that there will a newline between each + pathname. + +2008-02-17 08:19 millert + + * Makefile.in: run sudo.man.pl when generating sudo.man.in + +2008-02-17 08:11 millert + + * configure, configure.in, sudo.man.pl: comment out SELinux manual + bits unless --with-selinux was specified + +2008-02-17 08:04 millert + + * sudoers.pod: document role and type defaults for SELinux + +2008-02-16 20:26 millert + + * sudo.c, sudo.cat, sudo.man.in, sudo.pod, sudo_usage.h.in: + Document "sudo -ll" and make "sudo -l -l" be equivalent. + +2008-02-15 15:23 millert + + * configure.in, configure: Treat k*bsd*-gnu like Linux, not BSD. + Fixes compilation problems on Debian GNU/kFreeBSD. + +2008-02-13 17:17 millert + + * auth/kerb5.c: Avoid Heimdal'isms introduced in the rev 1.32 + rewrite of verify_krb_v5_tgt() + +2008-02-13 07:28 millert + + * logging.c, logging.h, sudo.c: Remove dependence on + VALIDATE_NOT_OK in logging functions. Split log_auth() into + log_allowed() and log_denial() Replace mail_auth() with + should_mail() and a call to send_mail() + +2008-02-10 18:06 millert + + * ldap.c: Add debugging so we can tell if the krb5 ccache is + accessible + +2008-02-10 17:34 millert + + * INSTALL: mention --with-selinux + +2008-02-09 09:48 millert + + * configure: regen + +2008-02-09 09:43 millert + + * selinux.c: add Sudo tag + +2008-02-09 09:30 millert + + * Makefile.in, config.h.in, configure.in, def_data.c, def_data.h, + def_data.in, gram.c, gram.h, gram.y, ldap.c, parse.c, parse.h, + pathnames.h.in, selinux.c, sesh.c, sudo.c, sudo.cat, sudo.h, + sudo.man.in, sudo.pod, sudo_usage.h.in, sudoers.ldap.cat, + sudoers.ldap.man.in, sudoers.ldap.pod, testsudoers.c, toke.c, + toke.l: Add support for SELinux RBAC. Sudoers entries may + specify a role and type. There are also role and type defaults + that may be used. To make sure a transition occurs, when using + RBAC commands are executed via the new sesh binary. Based on + initial changes from Dan Walsh. + +2008-02-08 08:18 millert + + * lbuf.c, ldap.c, parse.c, sudo.c, sudo.h, sudo_nss.c: Add long + list (sudo -ll) support for printing verbose LDAP and sudoers + file entries. Still need to update manual. + +2008-02-03 10:43 millert + + * ldap.c, parse.c, sudo.h, sudo_nss.c, sudo_nss.h: Unify the -l + output for file and ldap based sudoers and use lbufs for both. + The ldap output does not currently include options that cannot be + represented as tags. This will be remedied in a long list output + mode to come. + +2008-01-27 16:37 millert + + * set_perms.c: Use a specific error message for errno == EAGAIN + when setuid() et al fails. On Linux systems setuid() will fail + with errno set to EAGAIN if changing to the new uid would result + in a resource limit violation. + +2008-01-27 16:34 millert + + * sudo.c: Unlimit nproc on Linux systems where calling the setuid() + family of syscalls causes the nroc resource limit to be checked. + The limits will be reset by pam_limits.so when PAM is used. In + the non-PAM case the nproc limit will remain unlimited but there + doesn't seem to be a way around that other than having sudo parse + /etc/security/limits.conf directly. + +2008-01-27 16:31 millert + + * env.c, sudo.c, sudo.pod: Only read /etc/environment on Linux and + AIX + +2008-01-23 06:33 millert + + * configure, configure.in: Use SUDO_DEFINE_UNQUOTED instead of + AC_DEFINE_UNQUOTED to prevent ldap.conf and ldap.secret paths + from going into config.h. Avoid single quotes in variable + expansion when using SUDO_DEFINE_UNQUOTED since in some versions + of bash they will end up literally in the resulting define. + +2008-01-21 13:22 millert + + * README.LDAP: mention --with-nsswitch=no + +2008-01-21 11:43 millert + + * configure, configure.in: ldap_ssl.h depends on ldap.h being + included first + +2008-01-21 11:07 millert + + * configure, configure.in, ldap.c, config.h.in: Include ldap_ssl.h + if we can find it. Needed for the ldapssl_set_strength defines + on HP-UX at least. + +2008-01-21 10:02 millert + + * TODO, sudoers.ldap.pod: sync + +2008-01-21 10:01 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.ldap.cat, + sudoers.ldap.man.in, sudoers.man.in, visudo.cat, visudo.man.in: + regen + +2008-01-21 10:00 millert + + * Makefile.in: Use 78n line length when formatting cat pages. + +2008-01-21 09:50 millert + + * README.LDAP: Remove redundant info that is now in + sudoers.ldap.pod + +2008-01-20 16:18 millert + + * sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod: + Reorganize the first section a bit. Substitute the proper path + for /etc/sudoers. + +2008-01-20 10:17 millert + + * sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod: + Substitute values for ldap.conf, ldap.secret and nsswitch.conf + Move schema into EXAMPLES + +2008-01-20 10:15 millert + + * configure.in, configure: Substitute values for ldap.conf, + ldap.secret and nsswitch.conf into sudoers.ldap.man. + +2008-01-19 20:35 millert + + * configure, configure.in: substitute for sudoers.ldap.man + +2008-01-19 20:34 millert + + * Makefile.in: Fix cut & pasto introduced when adding sudoers.ldap + man page. + +2008-01-19 20:25 millert + + * sudoers.ldap.pod, sudoers.ldap.cat, sudoers.ldap.man.in: Fill in + some of the missing pieces. Still needs some reorganization and + editing. + +2008-01-19 15:06 millert + + * Makefile.in, sudoers.ldap.cat, sudoers.ldap.man.in, + sudoers.ldap.pod: Beginnings of a sudoers.ldap man page. + Currently, much of the information is adapted from README.LDAP. + +2008-01-18 17:32 millert + + * pwutil.c: When copying gr_mem we must guarantee that the storage + space for gr_mem is properly aligned. The simplest way to do + this is to simply store gr_mem directly after struct group. This + is not a problem for gr_passwd or gr_name as they are simple + strings. + +2008-01-18 16:47 millert + + * ldap.c: Fix a typo/thinko in one of the calls to + sudo_ldap_check_user_netgroup(). From Marco van Wieringen. + +2008-01-17 15:44 millert + + * config.h.in, configure, configure.in, ldap.c: include + in ldap.c if available + +2008-01-16 18:20 millert + + * gram.c, gram.y: Make sure we define SIZE_MAX for yacc's + skeleton.c + +2008-01-16 13:03 millert + + * tgetpass.c: Use TCSAFLUSH when restoring terminal settings (and + echo) to guarantee that any pending output is discarded + +2008-01-15 17:18 millert + + * sudoers: no longer need to specify SETENV when user has sudo ALL + +2008-01-15 09:40 millert + + * testsudoers.c: sync user_args size calculation with sudo.c Add -g + group option, renaming old -g to -G Add set_runasgr() and + set_runaspw() and use them + +2008-01-15 09:23 millert + + * sudo.h, sudo.c: Make set_runaspw static void + +2008-01-15 09:17 millert + + * testsudoers.c, visudo.c: g/c set_runaspw stub + +2008-01-15 07:28 millert + + * configure, configure.in: Don't add -llber twice. + +2008-01-14 06:40 millert + + * ldap.c: fix typo + +2008-01-13 15:39 millert + + * gram.c: regen + +2008-01-13 14:57 millert + + * configure, configure.in: Fix check that determines whether -llber + is required. + +2008-01-13 14:22 millert + + * config.h.in, configure, configure.in, README.LDAP, ldap.c: For + netscape-based LDAP, use ldapssl_set_strength() to implement the + checkpeer ldap.conf option. + +2008-01-13 09:49 millert + + * auth/kerb5.c: Delay krb5_cc_initialize() until we actually need + to use the cred cache, which is what krb5_verify_user() does. + Better cleanup on failure. + +2008-01-12 12:40 millert + + * auth/kerb5.c: Rewrite verify_krb_v5_tgt() based on what heimdal's + krb5_verify_user() does. + +2008-01-09 14:58 millert + + * gram.c: The U suffix on constants is an ANSI feature + +2008-01-09 12:08 millert + + * configure.in, configure: Add check for ber_set_option() in -llber + +2008-01-06 19:02 millert + + * README.LDAP: default if no nsswitch.conf is files only + +2008-01-06 17:28 millert + + * README.LDAP: don't tell people to mail aaron about LDAP stuff + +2008-01-06 12:32 millert + + * README.LDAP: timelimit and bind_timelimit + +2008-01-06 08:54 millert + + * ChangeLog: sync + +2008-01-06 07:56 millert + + * ldap.c: Move ldap.secret reading into a separate function. + +2008-01-05 19:09 millert + + * check.c: user_runas -> runas_pw + +2008-01-05 18:59 millert + + * TODO: sync + +2008-01-05 18:59 millert + + * check.c, sudo.pod, sudoers.pod: Add and document the %p escape in + the password prompt. Based on a patch from Patrick Schoenfeld. + +2008-01-05 18:25 millert + + * ldap.c: Check strlcpy() return values. + +2008-01-05 18:12 millert + + * ldap.c: refactor ldap binding code into sudo_ldap_bind_s() + +2008-01-05 16:35 millert + + * README.LDAP: Make it clear that host and uri can take multiple + parameters. URI is now supported for more than just openldap + nsswitch.conf does't accept "compat" + +2008-01-05 16:27 millert + + * sudo.c: comment cleanup and update (c) year + +2008-01-05 16:25 millert + + * parse.c, sudo_nss.c: Move display_privs() and display_cmnd() from + parse.c to sudo_nss.c. This should make it possible to build an + LDAP-only sudo binary. + +2008-01-05 13:27 millert + + * ldap.c, parse.c, sudo.c, sudo.h, sudo_nss.h: Improve chaining of + multiple sudoers sources by passing in the previous return value + to the next in the chain + +2008-01-05 13:26 millert + + * gram.y: Free up parser data structures in sudo_file_close(). + +2008-01-05 08:13 millert + + * gram.c, parse.c: Free up parser data structures in + sudo_file_close(). + +2008-01-05 07:59 millert + + * ldap.c: Parse uri ourself if no ldap_initialize() is present Use + ldap_create() instead of deprecated ldap_init() Use + ldap_sasl_bind_s() instead of deprecated ldap_simple_bind_s() + +2008-01-05 07:56 millert + + * config.h.in, configure, configure.in: Add check for + ldap_sasl_bind_s() Remove -DLDAP_DEPRECATED from CFLAGS + +2008-01-04 09:56 millert + + * configure.in, configure, config.h.in: add check for ldap_create + +2008-01-03 16:11 millert + + * config.h.in, configure, configure.in, ldap.c: Add + sudo_ldap_get_first_rdn() to return the first rdn of an entry's + dn using the mechanism appropriate for the LDAP SDK in use. Use + ldap_unbind_ext_s() instead of deprecated ldap_unbind_s(). + Emulate ldap_unbind_ext_s() and ldap_search_ext_s() for SDK's + without them. + +2008-01-03 16:02 millert + + * lbuf.c: include unistd.h + +2008-01-03 11:05 millert + + * config.h.in, configure.in: fix typo in mtim_getnsec + +2008-01-02 15:29 millert + + * config.h.in, configure.in, configure: add check for st__tim in + struct stat as used by SCO + +2008-01-02 11:05 millert + + * ldap.c: use ldap_search_ext_s instead of deprecated ldap_search_s + +2008-01-02 10:09 millert + + * Makefile.in, TODO, sudo.cat, sudo.man.in: add sudo_nss.h to HDRS + +2008-01-01 19:04 millert + + * ldap.c: Replace deprecated ldap_explode_dn() with calls to + ldap_str2dn() and ldap_rdn2str(). + +2008-01-01 18:37 millert + + * ldap.c: Use ldap_get_values_len()/ldap_value_free_len() instead + of the deprecated ldap_get_values()/ldap_value_free(). + +2008-01-01 17:07 millert + + * TODO, ChangeLog: sync + +2008-01-01 17:06 millert + + * gettime.c, sudo.c: Remove some already fixed XXXs + +2008-01-01 17:03 millert + + * ldap.c: Same return value as non-existent sudoers if LDAP was + unable to connect. + +2008-01-01 16:52 millert + + * sudo.pod: mention /etc/environment + +2008-01-01 16:42 millert + + * UPGRADE, WHATSNEW, README.LDAP: Update to reflect recent + developments. + +2008-01-01 16:42 millert + + * sudo.c: Print nsswitch.conf, ldap.conf and ldap.secret paths in + -V output. + +2008-01-01 16:25 millert + + * ldap.c: When building up a query don't list groups in the aux + group vector that are the same as the passwd file group. On most + systems the first gid in the group vector is the same as the + passwd entry gid. + +2008-01-01 14:01 millert + + * env.c, ldap.c: Define LDAPNOINIT before calling ldap_init(), etc. + to disable user ldaprc and system defaults that could affect how + LDAP works. + +2008-01-01 13:21 millert + + * INSTALL, configure, configure.in, pathnames.h.in, sudo.c, + sudo_nss.c, sudo_nss.h: Rename read_nss -> sudo_read_nss Add + --with-nsswitch to allow users to specify nsswitch.conf path or + disable it. If --with-nsswitch=no but --with-ldap, order is + LDAP, then sudoers. Fix --with-ldap-conf-file and + --with-ldap-secret-file + +2008-01-01 13:12 millert + + * parse.c: Honor def_ignore_local_sudoers + +2007-12-31 16:44 millert + + * ldap.c: no longer need to check def_ignore_local_sudoers here + +2007-12-31 16:36 millert + + * parse.c: Refactor group vector resetting into a function and also + call it from display_cmnd. Stop after the first sucessful match + in display_cmnd. Print a newline between each display_privs + method. + +2007-12-31 16:23 millert + + * parse.c: fix double free introduced in rev 1.218 + +2007-12-31 16:10 millert + + * ldap.c: belt and suspenders; zero out result after freeing it + +2007-12-31 15:04 millert + + * env.c, fileops.c, ldap.c, sudo.h, sudo_nss.c: Refactor line + reading into a separate function, sudo_parseln(), which removes + comments, leading/trailing whitespace and newlines. May want to + rethink the use of sudo_parseln() for /etc/ldap.secret + +2007-12-31 14:26 millert + + * parse.c, sudo.c: Make the inability to read the sudoers file a + non-fatal error if there are other sudoers sources available. + sudoers_file_lookup now returns "not OK" if sudoers was not + present + +2007-12-31 14:24 millert + + * ldap.c: make it clear that the global options are from LDAP + +2007-12-31 14:13 millert + + * logging.c: allocate proper amount of space for error string + +2007-12-31 10:24 millert + + * sudo_nss.c, sudo_nss.h: actual sudo nss code + +2007-12-31 10:08 millert + + * ldap.c, parse.c, sudo.c, sudo.h: nss-ify display_privs and + display_cmnd. + +2007-12-31 07:54 millert + + * defaults.c, parse.c, testsudoers.c, visudo.c: move + update_defaults() to parse.c + +2007-12-31 07:39 millert + + * Makefile.in, ldap.c, list.c, parse.c, parse.h, sudo.c, sudo.h: + Use nsswitch to hide some sudoers vs. ldap implementation details + and reduce the number of #ifdef LDAP TODO: fix display routines + and error handling + +2007-12-28 11:20 millert + + * Makefile.in, README.LDAP, ldap.c, pathnames.h.in, sudo.c, sudo.h: + First cut at nsswitch.conf support. Further reorganizaton and + related changes are forthcoming. + +2007-12-21 16:53 millert + + * env.c, pathnames.h.in, sudo.c, sudo.h: Add support for reading + and /etc/environment file. Still needs to be documented and + should probably only applies to OSes that have it (AIX and Linux, + maybe others). + +2007-12-21 16:20 millert + + * ldap.c: include limits.h + +2007-12-20 10:02 millert + + * WHATSNEW: reword LDAP SASL + +2007-12-19 16:40 millert + + * TODO: sync + +2007-12-19 16:39 millert + + * README.LDAP: Add an example sudoRole, clarify netscape vs. + openldap a bit more + +2007-12-19 14:42 millert + + * README.LDAP: Be clear on what is OpenLDAP vs. Netscape-derived + +2007-12-19 14:28 millert + + * config.h.in, configure, configure.in, ldap.c: Use ldapssl_init() + for ldaps support instead of trying to do it manually with + ldap_init() + ldapssl_install_routines(). Use tls_cert and + tls_key for cert7.db and key3.db respectively. Don't print + debugging info for options that are not set. Add warning if + start_tls specified when not supported. + +2007-12-19 14:25 millert + + * ldap.c: fix compilation on solaris + +2007-12-19 14:23 millert + + * Makefile.in: add missing .h and .c files for missing lib objs + +2007-12-18 09:54 millert + + * ldap.c: fix LDAP_OPT_NETWORK_TIMEOUT setting + +2007-12-17 20:10 millert + + * ldap.c: fix compilation on Solaris + +2007-12-17 10:14 millert + + * configure, configure.in: fix typo + +2007-12-17 08:08 millert + + * README.LDAP: try to clear up which variables are for OpenLDAP and + which are for netscape-derived SDKs + +2007-12-17 07:31 millert + + * config.h.in, configure, configure.in, ldap.c: Add support for + "ssl on" in both netscape and openldap flavors. Only the + OpenLDAP flavor has been tested. + +2007-12-17 07:28 millert + + * logging.c, sudo.c, sudo.h: Call cleanup() before exit in + log_error() instead of calling sudo_ldap_close() directly. + ldap_conn can now be static to sudo.c + +2007-12-16 20:02 millert + + * sudo.c: ld -> ldap_conn + +2007-12-16 14:42 millert + + * logging.c, sudo.c, sudo.h: Better ldap cleanup. + +2007-12-16 14:08 millert + + * ldap.c: Distinguish between LDAP conf settings that are + connection-specific (which take an ld pointer) and those that are + default settings (which do not). + +2007-12-14 16:46 millert + + * ldap.c: Improved warnings on error. + +2007-12-14 15:59 millert + + * ldap.c: Make ldap config table driven and set the config *after* + we open the connection. + +2007-12-13 16:41 millert + + * ldap.c: fix LDAP_OPT_X_CONNECT_TIMEOUT compat define + +2007-12-13 09:13 millert + + * configure, configure.in: some operating systems need to link with + -lkrb5support when using krb5 + +2007-12-10 17:12 millert + + * WHATSNEW: minor update + +2007-12-10 10:56 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in: regen + +2007-12-07 19:17 millert + + * TODO, ChangeLog: sync + +2007-12-07 19:09 millert + + * ldap.c, schema.OpenLDAP, schema.iPlanet, sudoers2ldif: add -g + support for LDAP + +2007-12-03 11:36 millert + + * WHATSNEW, sudo.c, sudo.pod, sudo_usage.h.in: The -i and -s flags + can now take an optional command. + +2007-12-02 12:13 millert + + * def_data.c, def_data.h, def_data.in, sudo.c, sudo.pod, + sudoers.pod, auth/pam.c: Add passprompt_override flag to sudoers + that will cause the prompt to be overridden in all cases. This + flag is also set when the user specifies the -p flag. + +2007-12-01 19:51 millert + + * sudo.c: Move setting of login class until after sudoers has been + parsed. Set NewArgv[0] for -i after runas_pw has been set. + +2007-12-01 19:34 millert + + * configure, configure.in: Move the dgettext check. + +2007-12-01 11:22 millert + + * config.h.in, configure, configure.in, auth/pam.c: Add basic + support for looking up the string "Password: " in the PAM + localized text db. This allows us to determine whether the PAM + prompt is the default "Password: " one even if it has been + localized. + + TODO: concatenate non-std PAM prompts and user-specified sudo + prompts. + +2007-11-27 18:40 millert + + * Makefile.in, config.h.in, configure.in, parse.c, set_perms.c, + sudo.c, configure, sudo.h: Use AC_FUNC_GETGROUPS instead of a + home-grown attempt that was insufficient. + +2007-11-27 12:13 millert + + * configure, acsite.m4, interfaces.c, memrchr.c: Fix typos; + Martynas Venckus + +2007-11-25 19:26 millert + + * set_perms.c: Don't assume runas_pw is set; it may not be in the + -g case. + +2007-11-25 08:07 millert + + * logging.c, set_perms.c: Set aux group vector for PERM_RUNAS and + restore group vector for PERM_ROOT if we previously changed it. + Stash the runas group vector so we don't have to call initgroups + more than once. Also add no-op check to check_perms. + +2007-11-21 15:11 millert + + * WHATSNEW, check.c, def_data.in, defaults.c, gram.c, gram.h, + gram.y, ldap.c, logging.c, match.c, mon_systrace.c, parse.c, + parse.h, pwutil.c, set_perms.c, sudo.c, sudo.cat, sudo.h, + sudo.man.in, sudo.pod, sudo_usage.h.in, sudoers.cat, + sudoers.man.in, sudoers.pod, testsudoers.c, toke.c, visudo.c, + visudo.cat, visudo.man.in: Add support for runas groups. This + allows the user to run a command with a different effective + group. If the -g option is specified without -u the command will + be run as the current user (only the group will change). the -g + and -u options may be used together. TODO: implement runas group + for ldap improve runas group documentation add + testsudoers support + +2007-11-21 15:02 millert + + * configure, configure.in: fix setting of mandir + +2007-11-21 14:26 millert + + * sudo.pod, sudoers.pod: document that ALL implies SETENV + +2007-11-21 13:50 millert + + * ldap.c: s/setenv_ok/setenv_implied/g + +2007-11-21 13:44 millert + + * ldap.c: hostname_matches() returns TRUE on match in sudo 1.7. + +2007-11-21 13:26 millert + + * ldap.c: use strcmp, not strcasecmp when comparing ALL + +2007-11-21 11:41 millert + + * ldap.c: Make sudo ALL imply setenv. Note that unlike with + file-based sudoers this does affect all the commands in the + sudoRole. + +2007-11-21 11:05 millert + + * gram.c, gram.y, parse.c, parse.h: sudo "ALL" now implies the + SETENV tag but, unlike an explicit tag, it is not passed on to + other commands in the list. + +2007-11-21 11:02 millert + + * visudo.c: Add missing sudo_setpwent() and sudo_setgrent() calls. + Also use sudo_getpwuid() instead of getpwuid(). + +2007-11-15 11:16 millert + + * sudoers: Expand on the dangers of not using visudo to edit + sudoers. + +2007-11-08 07:24 millert + + * parse.c: Don't quote *?[]! on output since the lexer does not + strip off the backslash when reading those in. + +2007-11-07 13:16 millert + + * glob.c: expand "u_foo" types to "unsigned foo" to avoid + compatibility issues. + +2007-11-04 08:33 millert + + * logging.c: Refactor log line generation in to new_logline(). + +2007-10-25 09:23 millert + + * TROUBLESHOOTING: fix typo + +2007-10-24 12:41 millert + + * config.h.in, configure, configure.in, interfaces.c, interfaces.h, + match.c: Add configure check for struct in6_addr instead of + relying on AF_INET6 since some systems define AF_INET6 but do not + include IPv6 support. + +2007-10-21 09:29 millert + + * configure, configure.in: Fix block to add -lutil for FreeBSD and + NetBSD when logincap is in use. + +2007-10-19 22:28 millert + + * configure, configure.in: POSIX states that struct timespec be + declared in time.h so check there regardless of the value of + TIME_WITH_SYS_TIME. + +2007-10-17 11:37 millert + + * tgetpass.c: Instead of defining a macro to call the appropriate + method for turning on/off echo, just define tc[gs]etattr() and + the related defines that use the correct terminal ioctls if + needed. Also go back to using TCSAFLUSH instead of TCSADRAIN on + all but QNX. + +2007-10-08 20:18 millert + + * Makefile.in: g/c @ALLOCA@ + +2007-10-08 20:07 millert + + * configure: regen + +2007-10-08 20:04 millert + + * INSTALL, config.h.in, configure.in, auth/pam.c: Add + --disable-pam-session configure option to disable calling + pam_{open,close}_session. May work around bugs in some PAM + implementations. + +2007-10-08 12:00 millert + + * tgetpass.c: quiet gcc warnings + +2007-10-08 08:41 millert + + * tgetpass.c: Avoid printing the prompt if we are already + backgrounded. E.g. if the user runs "sudo foo &" from the shell. + In this case, the call to tcsetattr() will cause SIGTTOU to be + delivered. + +2007-09-15 16:07 millert + + * def_data.c, def_data.h, def_data.in: Reorder things such that the + definition of env_reset come right before the env variable lists. + +2007-09-15 07:50 millert + + * parse.h: Shrink type and seqno in struct alias from int to + u_short + +2007-09-15 07:24 millert + + * alias.c, match.c, parse.c, parse.h: Add a sequence number in the + aliases for loop detection. If we find an alias with the seqno + already set to the current (global) value we know we've visited + it before so ignore it. + +2007-09-13 19:05 millert + + * TODO, sudo.c, sudo.h, auth/pam.c: PAM wants the full tty path so + add user_ttypath which holds the full path to the tty or is NULL + if no tty was present. + +2007-09-13 18:42 millert + + * auth/pam.c: Set PAM_RHOST to work around a bug in Solaris 7 and + lower that results in a segv. + +2007-09-11 15:43 millert + + * gram.c: regen + +2007-09-11 15:42 millert + + * alias.c, defaults.c, gram.y, list.c, list.h, match.c, parse.c, + parse.h, testsudoers.c, visudo.c: rename lh_ -> tq_ + +2007-09-10 17:33 millert + + * alloc.c: remove some useless casts + +2007-09-10 17:32 millert + + * alloc.c: pull in inttypes.h for SIZE_MAX; we avoid stdint.h since + inttypes.h predates the final C99 spec and the standard specifies + that it shall include stdint.h anyway + +2007-09-06 12:39 millert + + * Makefile.in, alloca.c, configure.in: Since we ship with a + pre-generated parser there is no need to ship a bogus alloca + implementation. + +2007-09-06 12:22 millert + + * configure: regen + +2007-09-06 12:19 millert + + * configure.in: remove initial setting of CHECKSIA, we require that + it be unset if not used + +2007-09-06 11:55 millert + + * Makefile.in: add list.c to SRCS + +2007-09-06 07:18 millert + + * configure: regen + +2007-09-06 07:17 millert + + * configure.in: only do SIA checks on Digital Unix + +2007-09-05 18:50 millert + + * sudoers.cat, sudoers.man.in: regen + +2007-09-05 18:48 millert + + * ChangeLog, TODO: sync + +2007-09-05 18:39 millert + + * auth/kerb5.c: Remove call to krb5_cc_register() as it is not + needed for modern kerb5. + +2007-09-05 18:16 millert + + * configure: regen + +2007-09-05 18:16 millert + + * configure.in, aclocal.m4: New method for setting the default + authentication type and avoiding conflicts in auth types. + +2007-09-05 14:45 millert + + * match.c, parse.c, testsudoers.c: Each entry in a cmndlist now has + an associated runaslist so no need to keep track of the most + recent non-NULL one. + +2007-09-04 18:51 millert + + * ldap.c: back out partial ldaps support mistakenly committed + +2007-09-04 10:57 millert + + * ldap.c: Add support for unix groups and netgroups in sudoRunas + +2007-09-03 16:28 millert + + * sudo_edit.c: Fix sudoedit of a non-existent file. From Tilo + Stritzky. + +2007-09-02 17:05 millert + + * configure: regen + +2007-09-02 17:05 millert + + * INSTALL: update --passprompt escape info + +2007-09-02 17:03 millert + + * configure.in: remove now-bogus comment and update copyright date + +2007-09-02 16:35 millert + + * configure.in: Fix up use of with_passwd + +2007-09-02 16:25 millert + + * acsite.m4, config.guess, config.sub, configure.in, ltmain.sh: + Update to autoconf-2.61 andf libtool-1.5.24 + +2007-09-02 16:17 millert + + * Makefile.in: "cmp -s" not just cmp Add @datarootdir@ to quiet + autoconf-2.61 + +2007-09-01 17:39 millert + + * gram.c: regen + +2007-09-01 17:39 millert + + * gram.y: move tags and runaslist propagation to be earlier + +2007-09-01 09:34 millert + + * visudo.c: If -f flag given use the permissions of the original + file as a template + +2007-09-01 08:45 millert + + * gram.y: prevent a double free() when re-initing the parser + +2007-08-31 19:30 millert + + * configure: regen + +2007-08-31 19:30 millert + + * aclocal.m4, alias.c, alloc.c, config.h.in, configure.in, env.c, + ldap.c, list.c, list.h, memrchr.c, parse.c, parse.h, pwutil.c, + redblack.c, redblack.h, snprintf.c, sudo.c, sudo.h, + testsudoers.c, visudo.c, zero_bytes.c, auth/API, auth/afs.c, + auth/bsdauth.c, auth/kerb4.c, auth/kerb5.c, auth/pam.c, + auth/securid.c, auth/securid5.c, auth/sia.c, auth/sudo_auth.h: + Remove support for compilers that don't support void * + +2007-08-31 19:14 millert + + * gram.c: regen + +2007-08-31 19:13 millert + + * Makefile.in, alias.c, defaults.c, gram.y, list.c, list.h, + match.c, parse.c, parse.h, testsudoers.c, visudo.c: Move list + manipulation macros to list.h and create C versions of the more + complex ones in list.c. The names have been down-cased so they + appear more like normal functions. + +2007-08-31 17:21 millert + + * Makefile.in: Fix cmp command when regenerating parser. Make + gram.o the first dependency for all programs so gram.h will be + generated before anything that needs it. + +2007-08-31 13:56 millert + + * parse.h, gram.y: Convert NEW_DEFAULT anf NEW_MEMBER into static + functions. + +2007-08-30 21:21 millert + + * match.c, parse.c, testsudoers.c: Use LH_FOREACH_REV when checking + permission and short-circuit on the first non-UNSPEC hit we get + for the command. This means that instead of cycling through the + all the parsed sudoers entries we start at the end and work + backwards and quit after the first positive or negative match. + +2007-08-30 21:13 millert + + * gram.c: regen + +2007-08-30 21:12 millert + + * defaults.c, gram.y, parse.c, parse.h, testsudoers.c, visudo.c: + Change list head macros to take a pointer, not a struct. + +2007-08-30 20:46 millert + + * gram.c: regen + +2007-08-30 20:46 millert + + * gram.y: Propagate the runasspec from one command to the next in a + cmndspec. + +2007-08-30 16:15 millert + + * match.c: Replace has_meta() with a macro that calls strpbrk(). + +2007-08-30 16:04 millert + + * gram.c: regen + +2007-08-30 13:26 millert + + * alias.c, defaults.c, gram.y, match.c, parse.c, parse.h, + testsudoers.c, visudo.c: Use a list head struct when storing the + semi-circular lists and convert to tail queues in the process. + This will allow us to reverse foreach loops more easily and it + makes it clearer which functions expect a list as opposed to a + single member. + + Add macros for manipulating lists. Some of these should become + functions. + + When freeing up a list, just pop off the last item in the queue + instead of going from head to tail. This is simpler since we + don't have to stash a pointer to the next member, we always just + use the last one in the queue until the queue is empty. + + Rename match functions that take a list to have list in the name. + Break cmnd_matches() into cmnd_matches() and cmndlist_matches. + +2007-08-30 13:12 millert + + * parse.c: Fix pasto, append "!" not negated (which is an int) for + sudo -l output. + +2007-08-30 12:45 millert + + * Makefile.in: Remove the dependency of gram .h on gram.y, the .c + dependency is enough. Only move y.tab.h to gram.h if it is + different; avoids needless rebuilding. + +2007-08-27 15:51 millert + + * sudoers.pod: Defaults lines may be associated with lists of + users, hosts, commands and runas users, not just single entries. + +2007-08-26 17:42 millert + + * Makefile.in: Revert the "cmp" portion of the last diff, it + doesn't make sense. + +2007-08-26 17:10 millert + + * Makefile.in: Remove *.lo for clean: When generating the parser, + only move the generated files into place if they differ from the + existing ones. + +2007-08-24 22:47 millert + + * toke.c, toke.l: Replace IPV6 regexp with a much simpler + (readable) one and add an extra check when it matches to make + sure we have a valid address. + +2007-08-24 22:36 millert + + * match.c: Fix thinko introduced when merging IPV6 support. + +2007-08-24 14:23 millert + + * HISTORY, LICENSE: regen + +2007-08-24 14:23 millert + + * license.pod: add 2007 + +2007-08-24 14:19 millert + + * UPGRADE: mention #uid vs. comment pitfall + +2007-08-24 09:50 millert + + * acsite.m4: Merge in a patch from the libtool cvs that fixes a + problem with the latest autoconf. From Stepan Kasal. + +2007-08-23 20:28 millert + + * parse.h: Back out he XOR swap trick, it is slower than a temp + variable on modern CPUs. + +2007-08-23 20:14 millert + + * gram.c: regen + +2007-08-23 20:14 millert + + * gram.y, parse.h: Convert the tail queue to a semi-circle queue + and use the XOR swap trick to swap the prev pointers during + append. + +2007-08-23 15:31 millert + + * parse.h: remove useless statement + +2007-08-23 07:47 millert + + * toke.c, toke.l: Refactor #include parsing into a separate + function and return unparsed chars (such as newline or comment) + back to the lexer. + +2007-08-22 18:56 millert + + * WHATSNEW: mention better uid support + +2007-08-22 18:55 millert + + * sudoers.pod: Users may now consist of a uid. + +2007-08-22 18:39 millert + + * gram.c, gram.h, toke.c: regen + +2007-08-22 18:32 millert + + * parse.c: Use lbuf_append_quoted() for sudo -l output to quote + characters that would require quoting in sudoers. + +2007-08-22 18:31 millert + + * lbuf.c, lbuf.h: Add lbuf_append_quoted() which takes a set of + characters which should be quoted with a backslash when + displayed. + +2007-08-22 18:28 millert + + * toke.l: Require that the first character after a comment not be a + digit or a dash. This allows us to remove the GOTRUNAS state and + treat uid/gids similar to other words. It also means that we can + now specify uids in User_Lists and a User_Spec may now contain a + uid. + +2007-08-22 18:23 millert + + * gram.y, toke.l: Replace RUNAS token with '(' and ')' tokens to + make the runas portion of the grammar more natural. + +2007-08-22 06:35 millert + + * Makefile.in, README, BUGS: The BUGS file is history + +2007-08-21 09:19 millert + + * toke.c, toke.l: Allow comments after a RunasAlias as long as the + character after the pound sign isn't a digit or a dash. + +2007-08-20 20:43 millert + + * WHATSNEW: Glob support was back-ported to 1.6.9 + +2007-08-20 19:59 millert + + * Makefile.in: remove sudo_usage.h in distclean + +2007-08-20 19:24 millert + + * parse.c: If a Defaults value contains a blank, double-quote the + string. + +2007-08-20 19:19 millert + + * toke.c, toke.l: Properly deal with Defaults double-quoted strings + that span multiple lines using the line continuation char. + Previously, the entire thing, including the continuation char, + newline, and spaces was stored as-is. + +2007-08-20 10:46 millert + + * sudo.c: Be consistent when using single quotes and backticks. + +2007-08-19 16:48 millert + + * Makefile.in, configure, configure.in, lbuf.c, lbuf.h, parse.c, + sudo.c, sudo_usage.h.in: Add new linebuf code to do appends of + dynamically allocated strings and word-wrapped output. Currently + used for sudo's usage() and sudo -l output. Sudo usage strings + are now in sudo_usage.h which is generated at configure time. + +2007-08-18 08:22 millert + + * sudo.h, parse.c, sudo.c: Fix line wrapping in usage() and use the + actual tty width instead of assuming 80. + +2007-08-17 18:32 millert + + * history.pod: some more info + +2007-08-17 17:28 millert + + * history.pod: Mentioned Chris Jepeway's parser and also the new + one that is in sudo 1.7. + +2007-08-16 09:38 millert + + * sudo.pod, visudo.pod: For the options list, add flag args where + appropriate and increase the indent level so there is room for + them. + +2007-08-15 13:49 millert + + * parse.c: Fix some spacing in "sudo -l" and add a comment about + some bogosity in the line wrapping. + +2007-08-15 11:21 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, + visudo.man.in, visudo.cat: regen + +2007-08-15 11:20 millert + + * INSTALL, Makefile.in, WHATSNEW, config.h.in, configure.in, + def_data.c, def_data.h, def_data.in, gram.c, gram.h, gram.y, + parse.c, parse.h, pathnames.h.in, sudo.c, sudo.h, sudoers.pod, + testsudoers.c, toke.c, toke.l: Remove monitor support until there + is a versino of systrace that uses a lookaside buffer (or we have + a better mechanism to use). + +2007-08-15 09:22 millert + + * configure.in, configure, config.h.in, sudo.c: use getaddrinfo() + instead of gethostbyname() if it is available + +2007-08-14 15:27 millert + + * parse.c, sudo.c: Deal with OSes where sizeof(gid_t) < + sizeof(int). + +2007-08-14 11:19 millert + + * interfaces.c: repair non-getifaddrs() code after ipv6 integration + +2007-08-14 10:04 millert + + * sudo.c: If we can open sudoers but fail to read the first byte, + close the file stream before trying again. + +2007-08-13 12:34 millert + + * gram.c, toke.c: regen + +2007-08-13 12:29 millert + + * gram.y, interfaces.c, interfaces.h, match.c, sudoers.pod, toke.l: + Add IPv6 support; adapted from patches by YOSHIFUJI Hideaki + +2007-08-13 12:23 millert + + * sudo.pod, sudoers.pod, visudo.pod: Add some missing markup Update + copyright + +2007-08-12 18:55 millert + + * configure, configure.in: fix sudo_noexec extension which got + broken in the libtool update + +2007-08-10 10:41 millert + + * Makefile.in: explicitly specify -Tascii to nroff + +2007-08-08 16:07 millert + + * logging.c: remove an ANSI-ism that crept in + +2007-08-06 20:37 millert + + * sudo.pod: Adjust list indents Prevent -- from being turned into + an em dash Use a list for the environment instead of a literal + paragraph + +2007-08-06 20:36 millert + + * visudo.pod: Use a list for the environment instead of an indented + literal paragraph. + +2007-08-06 20:33 millert + + * sudoers.pod: Adjust list indentation + +2007-08-06 20:31 millert + + * license.pod: add =head3 + +2007-08-06 10:24 millert + + * sudo.pod: mention that when specifying a uid for the -u option + the shell may require that the # be escaped + +2007-08-01 22:08 millert + + * match.c: Fix off by one in group matching. + +2007-07-31 14:04 millert + + * env.c: Fix typo: PYTHONINSPEC should be PYTHONINSPECT. From + David Krause. + +2007-07-30 10:45 millert + + * configure, configure.in: Add missing define of + HAVE_GSS_KRB5_CCACHE_NAME for the -lgssapi_krb5 case. + +2007-07-30 09:29 millert + + * aclocal.m4, configure.in, configure: Fix link tests such that new + gcc doesn't optimize away the test. + +2007-07-29 19:21 millert + + * sudo.pod, sudoers.pod, visudo.pod: add missing over/back + +2007-07-29 19:09 millert + + * sudo.pod, sudoers.pod, visudo.pod: Change FILES section to use + =item + +2007-07-29 18:32 millert + + * env.c: Add back allocation of the env struct in rebuild_env but + save a copy of the old pointer and free it before returning. + +2007-07-29 16:09 millert + + * env.c: Don't init the private environment in rebuild_env() since + it may have already been done implicitly + sudo_setenv/sudo_unsetenv. + + Multiply length by sizeof(char *) in memcpy/memmove when copying + the environment so we copy the full thing. + + Add missing set of parens so we deref the right pointer in + sudo_unsetenv when searching for a matching variable. + +2007-07-26 16:35 millert + + * sudo.pod, sudoers.pod, visudo.pod: Use file markup for paths in + the FILES section + +2007-07-26 10:04 millert + + * sudo.pod, sudoers.pod, visudo.pod: Don't capitalize sudo/visudo + +2007-07-26 07:28 millert + + * sudoers.pod: Sort sudoers options; based on a diff from Igor + Sobrado. + +2007-07-25 16:19 millert + + * sudo.pod, sudoers.pod, visudo.pod: Use 8 and 5 instead of + @mansectsu@ and @mansectform@ since the latter confuses pod2man. + The Makefile rules for the .man.in file will add @mansectsu@ and + @mansectform@ back in after pod2man is done anyway. + +2007-07-22 19:09 millert + + * LICENSE, Makefile.in, license.pod: Move license info to pod + format + +2007-07-22 18:43 millert + + * configure, configure.in, sudoers.pod: Substitute value of + path_info into sudoers man page. + +2007-07-22 16:40 millert + + * WHATSNEW: remove features that were back-ported to 1.6.9 + +2007-07-22 15:20 millert + + * sudo.c, sudo.pod, visudo.c, visudo.pod: Sort SYNOPSIS and sync + usage. From Igor Sobrado. + +2007-07-22 15:19 millert + + * env.c: Only need sudo_setenv/sudo_unsetenv if we are going to use + ldap_sasl_interactive_bind_s() but don't have + gss_krb5_ccache_name(). + +2007-07-22 08:23 millert + + * ChangeLog: rebuild without branch info + +2007-07-22 08:23 millert + + * Makefile.in: Add ChangeLog target + +2007-07-22 08:14 millert + + * auth/pam.c: Run cleanup code if the user hits ^C at the password + prompt. + +2007-07-22 08:13 millert + + * auth/pam.c: Some versions of pam_lastlog have a bug that will + cause a crash if PAM_TTY is not set so if there is no tty, set + PAM_TTY to the empty string. + +2007-07-20 09:32 millert + + * Makefile.in: ChageLog not Changelog + +2007-07-20 09:31 millert + + * ChangeLog: sync + +2007-07-20 09:29 millert + + * Makefile.in: CHANGE -> Changelog + +2007-07-19 20:23 millert + + * TODO: sync + +2007-07-19 19:53 millert + + * config.h.in, configure.in, configure, ldap.c: Add configure hooks + for gss_krb5_ccache_name() and the gssapi headers. + +2007-07-18 12:57 millert + + * env.c, sudo.c: rebuild_env() and insert_env_vars() no longer + return environment pointer, they set environ directly. + + No longer need to pass around an envp pointer since we just + operate on environ now. + + Add dosync argument to insert_env() that indicates whether it + should reset environ when realloc()ing env.envp. + + Use an initial size of 128 for the environment. + +2007-07-18 12:41 millert + + * env.c: Split sudo_setenv() into an external version and a version + only for use by rebuild_env(). + +2007-07-16 19:40 millert + + * ldap.c: Add support for using gss_krb5_ccache_name() instead of + setting KRB5CCNAME. Also use sudo_unsetenv() in the + non-gss_krb5_ccache_name() case if there was no KRB5CCNAME in the + original environment. TODO: configure setup for + gss_krb5_ccache_name() + +2007-07-16 18:44 millert + + * README.LDAP: add krb5_ccname + +2007-07-16 18:44 millert + + * README.LDAP, ldap.c: Add support for sasl_secprops in ldap.conf + +2007-07-16 18:39 millert + + * env.c, sudo.h: Add sudo_unsetenv() and refactor private env + syncing code into sync_env(). + +2007-07-16 07:27 millert + + * README.LDAP, ldap.c: The ldap.conf variable is sasl_auth_id not + sasl_authid. + +2007-07-15 15:44 millert + + * ldap.c, sudo.c, sudo.h: Add support for krb5_ccname in ldap.conf. + If specified, it will override the default value of KRB5CCNAME + in the environment for the duration of the call to + ldap_sasl_interactive_bind_s(). + +2007-07-15 15:41 millert + + * env.c, sudo.h: Remove format_env() Add sudo_setenv() to replace + most format_env() + insert_env() combinations. insert_env() no + longer takes a struct environment * + +2007-07-15 12:47 millert + + * ldap.c: Fix use_sasl vs. rootuse_sasl logic. + +2007-07-15 09:23 millert + + * README.LDAP, config.h.in, configure, configure.in, ldap.c: Add + support for SASL auth when connecting to an LDAP server. Adapted + from a diff by Tom McLaughlin. + +2007-07-14 16:32 millert + + * configure, configure.in: Only enable AIX or BSD auth if no other + exclusive auth method has been chosen. Allows people to e.g., + use PAM on AIX without adding --without-aixauth. A better + solution is needed to deal with default authentication since if a + non-exclusive method is chosen we will still get an error. + +2007-07-11 11:23 millert + + * HISTORY, Makefile.in, history.pod: Generate HISTORY from + history.pod (which is also used for web pages) + +2007-07-09 19:40 millert + + * sudo.man.in, sudoers.man.in: regen + +2007-07-09 19:25 millert + + * sudo.pod: Better explanation of environment handling in the sudo + man page. + +2007-07-09 15:13 millert + + * env.c, sudo.c: Defer setting user-specified env vars until after + authentication. + +2007-07-09 13:25 millert + + * env.c: honor def_default_path for PATH set on the command line + +2007-07-09 13:22 millert + + * sudo.c, env.c, sudo.pod, sudoers.pod: Allow user to set + environment variables on the command line as long as they are + allowed by env_keep and env_check. Ie: apply the same + restrictions as normal environment variables. TODO: deal with + secure_path + +2007-07-08 14:44 millert + + * sudo.c, sudo_edit.c: Call rebuild_env() in call cases. Pass + original envp to sudo_edit(). Don't allow -E or env var setting + in sudoedit mode. More accurate usage() when called as sudoedit. + +2007-07-08 14:41 millert + + * ldap.c: warn -> warning + +2007-07-08 14:11 millert + + * sudo.pod: add -c option to sudoedit synopsis + +2007-07-08 10:27 millert + + * TODO: udpate to reality + +2007-07-08 09:43 millert + + * parse.c: Use ALLOW/DENY instead of TRUE/FALSE when dealing with + the return value from {user,host,runas,cmnd}_matches(). Rename + *matches variables -> *match. Purely cosmetic. + +2007-07-08 09:30 millert + + * parse.c: Move setting of FLAG_NO_CHECK into the if(pwflag) block. + No change in behavior. + +2007-07-08 09:17 millert + + * sudoers: add SETENV tag + +2007-07-06 15:51 millert + + * parse.c: Make pwcheck local to the pwflag block. Use pwcheck + even if user didn't match since Defaults options may still apply. + +2007-07-06 14:51 millert + + * check.c, sudo.c: Do not update timestamp if user not validated by + sudoers. + +2007-07-06 10:14 millert + + * set_perms.c: for PERM_RUNAS, set the egid to the runas user's gid + and restore to the user's original in PERM_ROOT + +2007-07-06 10:04 millert + + * logging.c, mon_systrace.c, set_perms.c, sudo.h: PERM_FULL_ROOT is + now no different than PERM_ROOT so remove PERM_FULL_ROOT + +2007-07-06 09:49 millert + + * check.c: don't check timestamp mtime if we are just going to + remove it + +2007-07-06 09:33 millert + + * sudoers.pod: Move sudoers defaults parameters into their own + section. + +2007-07-05 20:21 millert + + * testsudoers.c: Reduce a level of indent by a few placed continue + statements. + +2007-07-05 20:20 millert + + * parse.c: Make matching but negated commands/hosts/runas entries + override a previous match as expected. Also reduce some levels + of indent by a few placed continue statements. + +2007-07-05 16:34 millert + + * parse.c: Print default runas in "sudo -l" if sudoers don't + specify one. + +2007-07-05 15:46 millert + + * match.c: Less hacky way of testing whether the domain was set. + +2007-07-04 15:50 millert + + * INSTALL: Mention pam-devel and openldap-devel for Linux + +2007-07-03 19:38 millert + + * README.LDAP: or vs. are + +2007-07-01 16:55 millert + + * sudo.c: fix typo in Solaris project support + +2007-07-01 09:40 millert + + * HISTORY: update + +2007-07-01 09:07 millert + + * sudo.c: Make -- on the command line match the manual page. The + implied shell case has been simplified as a result. + +2007-06-28 10:44 millert + + * sudoers2ldif: add simplistic support for sudoRunas; note that if + a sudoers entry contains multiple Runas users, all will apply to + the sudoRole + +2007-06-28 10:42 millert + + * sudoers2ldif: honor SETENV and NOSETENV tags + +2007-06-24 09:25 millert + + * mon_systrace.c: Redo setting of user_args. We now build up a + private copy of argv first and then replace the NULs with spaces. + +2007-06-24 09:19 millert + + * mon_systrace.c: getcwd() returns NULL on failure, not 0 on + success + +2007-06-24 07:39 millert + + * mon_systrace.c: allow chunksiz to reach 1 before erroring out + +2007-06-23 20:00 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat, + visudo.man.in: regen + +2007-06-23 19:58 millert + + * def_data.c, def_data.h, def_data.in, env.c, gram.c, gram.h, + gram.y, logging.c, parse.c, parse.h, sudo.c, sudo.h, sudo.pod, + sudoers.pod, toke.c, toke.l: Add support for setting environment + variables on the command line. This is only allowed if the + setenv sudoers options is enabled or if the command is prefixed + with the SETENV tag. + +2007-06-23 19:57 millert + + * README.LDAP: replace Aaron's email address with the sudo-workers + list + +2007-06-23 19:55 millert + + * configure: regen + +2007-06-21 20:35 millert + + * Makefile.in, README.LDAP, schema.OpenLDAP, schema.iPlanet: Break + schema out into separate files. + +2007-06-21 18:28 millert + + * auth/aix_auth.c: free message if set by authenticate() + +2007-06-21 13:03 millert + + * match.c: deal with NULL gr_mem + +2007-06-20 15:04 millert + + * config.h.in: regen + +2007-06-20 15:04 millert + + * configure.in: add template for HAVE_PROJECT_H + +2007-06-20 07:06 millert + + * closefrom.c: include fcntl.h + +2007-06-19 19:37 millert + + * INSTALL: mention --with-project + +2007-06-19 18:24 millert + + * config.h.in, configure.in, sudo.c: Add Solaris 10 "project" + support. From Michael Brantley. + +2007-06-19 17:27 millert + + * sudoers.pod: fix typo + +2007-06-19 17:22 millert + + * configure: regen + +2007-06-19 17:21 millert + + * configure.in: Fix preservation of LDFLAGS in the LDAP case. + +2007-06-19 17:00 millert + + * memrchr.c: Remove dependecy on NULL + +2007-06-19 15:37 millert + + * configure: regen + +2007-06-19 15:37 millert + + * aclocal.m4, configure.in: Can't use the regular autoconf + fnmatch() check since we need FNM_CASEFOLD so go back to our + custom one. + +2007-06-19 12:52 millert + + * env.c: Fix preserving of variables in env_keep. + +2007-06-19 07:10 millert + + * env.c: add XAUTHORIZATION + +2007-06-18 20:41 millert + + * UPGRADE: expand upon env resetting and mention that it began in + 1.6.9 not 1.7. + +2007-06-18 20:33 millert + + * sudoers.pod: Update descriptions of env_keep and env_check to + match current reality. + +2007-06-18 17:33 millert + + * env.c: Add LINGUAS to initial_checkenv_table. Add COLORS, + HOSTNAME, LS_COLORS, MAIL, PS1, PS2, XAUTHORITY to + intial_keepenv_table. + +2007-06-18 17:23 millert + + * env.c, logging.c: Treat USERNAME environemnt variable like + LOGNAME/USER + +2007-06-18 17:21 millert + + * env.c: Don't need to populate keepenv table with the contents of + the checkenv table. + +2007-06-18 08:57 millert + + * sudo.c: Don't force sudo into the C locale. + +2007-06-18 08:56 millert + + * env.c: Make env_check apply when env_reset it true. Environment + variables are passed through unless they contain '/' or '%'. + There is no need to have a variable in both env_check and + env_keep. + +2007-06-16 07:31 millert + + * visudo.c: Remove an duplicate lock_file() call and add a comment. + +2007-06-15 21:16 millert + + * UPGRADE: Add sudo 1.6.9 upgrade note. + +2007-06-14 12:23 millert + + * interfaces.c: Solaris will return EINVAL if the buffer used in + SIOCGIFCONF is too small. From Klaus Wagner. + +2007-06-14 12:03 millert + + * Makefile.in, config.h.in, configure, configure.in, memrchr.c, + logging.c, sudo.h: Redo the long syslog line splitting based on a + patch from Eygene Ryabinkin. Include memrchr() for systems + without it. + +2007-06-14 07:09 millert + + * configure.in: Since we need to be able to convert timespec to + timeval for utimes() the last 3 digits in the tv_nsec are not + significant. This makes the sudoedit file date comparison work + again. + +2007-06-13 13:41 millert + + * aclocal.m4, configure, configure.in: Add SUDO_ADD_AUTH macro to + deal with adding things to AUTH_OBJS. This deals with exclusive + authentication methods in a simple way. + +2007-06-12 13:08 millert + + * LICENSE: mkstemp.c is BSD code too. + +2007-06-12 09:21 millert + + * sudo.pod, sudoers.pod, visudo.pod: No commercial support for now. + +2007-06-11 18:27 millert + + * sudo.c: cleanenv() is no more. + +2007-06-10 18:37 millert + + * ChangeLog: Display branch info in Changelog + +2007-06-10 18:18 millert + + * utimes.c: Include config.h early so we have it for + TIME_WITH_SYS_TIME + +2007-06-10 18:00 millert + + * ChangeLog: Fix Changelog generation and update. + +2007-06-09 07:26 millert + + * closefrom.c: Use /proc/self/fd instead of /proc/$$/fd + + Move old-style fd closing into closefrom_fallback() and call that + if /proc/self/fd doesn't exist or the F_CLOSEM fcntl() fails + +2007-06-09 07:24 millert + + * config.h.in, configure.in, auth/kerb5.c: o use + krb5_verify_user() if available instead of doing it by hand + o use krb5_init_secure_context() if we have it + o pass an encryption type of 0 to krb5_kt_read_service_key() + instead of + ENCTYPE_DES_CBC_MD5 to let kerberos choose. + +2007-06-09 07:20 millert + + * env.c: Check TERM and COLORTERM for '%' and '/' characters. From + Debian. + +2007-06-09 07:17 millert + + * configure.in: Fix closefrom() substitution in the Makefile + +2007-06-09 07:15 millert + + * TROUBLESHOOTING: Mention alternate sudo pronunciation. + +2007-06-07 07:52 millert + + * env.c: Remove KRB5_KTNAME from environment. Allow COLORTERM. + +2007-06-07 07:22 millert + + * auth/kerb5.c: If we cannot get a valid service key using the + default keytab it is a fatal error. Fixes a bug where sudo could + be tricked into allowing access when it should not by a fake KDC. + From Thor Lancelot Simon. + +2007-05-12 08:56 millert + + * aclocal.m4, configure, configure.in: Update long long checks to + use AC_CHECK_TYPES and to cache values. + +2007-05-12 08:07 millert + + * aclocal.m4, configure.in: Use AC_FUNC_FNMATCH instead of a + homebrew fnmatch checker. We can't use AC_REPLACE_FNMATCH since + that assumes replacing with GNU fnmatch. + +2007-05-11 17:05 millert + + * configure, configure.in: Add closefrom() to LIB_OBJS not + SUDO_OBJS if it is missing since we need it for visudo now too. + +2007-04-24 14:44 millert + + * sudoers.pod: Attempt to clarify the bit talking about network + numbers w/o netmasks. + +2007-04-24 14:25 millert + + * sudo.pod: Clarify timestamp dir ownership sentence. + +2007-04-20 12:40 millert + + * auth/pam.c: Linux PAM now defines __LINUX_PAM__, not + __LIBPAM_VERSION. From Dmitry V. Levin. + +2007-04-16 12:13 millert + + * sudo.c: -i is also one of the mutually exclusive options to list + it in the warning message. Noted by Chris Pepper. + +2007-04-12 11:18 millert + + * visudo.pod: The sudoers variable is env_editor, not enveditor. + From Jean-Francois Saucier. + +2007-03-29 13:30 millert + + * redblack.c: I tracked down the original author so credit him and + include his license info. + +2007-02-06 13:25 millert + + * sudo.cat, sudo.man.in, sudo.pod, sudoers.cat, sudoers.man.in, + sudoers.pod: Fix typos; from Jason McIntyre. + +2007-02-06 13:23 millert + + * logging.c: Restore signal mask before calling reapchild(). Fixes + a possible race condition that could prevent sudo from properly + waiting for the child. + +2007-01-31 10:02 millert + + * pwutil.c: Don't declare pw_free() if we are not going to use it. + +2007-01-31 10:00 millert + + * env.c: Add NOEXEC support for AIX 5.3 which supports LDR_PRELOAD + and LDR_PRELOAD64. The 64-bit version is not currently + supported. Remove zero_env() prototype as it no longer exists. + +2006-12-11 13:21 millert + + * logging.c: Add "Auto-Submitted: auto-generated" line to sudo mail + for rfc 3834. + +2006-09-29 10:53 millert + + * auth/pam.c: If the user enters ^C at the password prompt, abort + instead of trying to authenticate with an empty password (which + causes an annoying delay). + +2006-08-17 11:26 millert + + * closefrom.c, config.h.in, configure, configure.in: Add fcntl + F_CLOSEM support to closefrom(); adapted from a diff by Darren + Tucker. + +2006-08-17 11:25 millert + + * pwutil.c: pw_free() is only used by sudo_freepwcache() so ifdef + it out too. + +2006-08-04 11:34 millert + + * config.sub, config.guess: Update to latest versions from + cvs.savannah.gnu.org + +2006-07-31 13:51 millert + + * pwutil.c, sudo_edit.c: Move password/group cache cleaning out of + sudo_end{pw,grp}ent() so we can close the passwd/group files + early. + +2006-07-31 13:50 millert + + * config.h.in, configure, configure.in, set_perms.c: Add seteuid() + flavor of set_perms() for systems without setreuid() or + setresuid() that have a working seteuid(). Tested on Darwin. + +2006-07-30 15:56 millert + + * mon_systrace.c: systrace_read() returns ssize_t + +2006-07-30 15:53 millert + + * configure, configure.in: Fix typo, -lldap vs. -ldap; from Tim + Knox. + +2006-07-28 13:12 millert + + * HISTORY: Fix typo; Matt Ackeret + +2006-07-17 08:25 millert + + * sudo.c: Print sudoers path in -V mode for root. + +2006-06-15 14:44 millert + + * ldap.c: Do a sub tree search instead of a base search (one level + in the tree only) for sudo right objects. This allows system + administrators to categorize the rights in a tree to make them + easier to manage. + +2005-12-28 13:52 millert + + * sudo.pod: fix typo + +2005-12-04 12:16 millert + + * ldap.c: Convert GET_OPT and GET_OPTI to use just 2 args. Add + timelimit and bind_timelimit support; adapted from gentoo. + +2005-11-23 18:57 millert + + * ldap.c: Support comments that start in the middle of a line + +2005-11-23 18:56 millert + + * configure.in, configure: Define LDAP_DEPRECATED until we start + using ldap_get_values_len() + +2005-11-18 09:55 millert + + * closefrom.c: Silence gcc -Wsign-compare; djm@openbsd.org + +2005-11-17 20:39 millert + + * error.c, sudo.c, sudo.h, testsudoers.c, visudo.c: cleanup() now + takes an int as an arg so it can be used as a signal handler too. + +2005-11-17 20:38 millert + + * sudo.c: Make a copy of the shell field in the passwd struct for + NewArgv to avoid a use after free situation after sudo_endpwent() + is called. + +2005-11-16 20:36 millert + + * Makefile.in, mkstemp.c, config.h.in, configure, configure.in: Add + mkstemp() for those poor souls without it. + +2005-11-15 09:25 millert + + * env.c: Add PERL5DB to list of environment variables to remove. + +2005-11-13 15:49 millert + + * mon_systrace.c, mon_systrace.h: Instead of calling the check + function twice with a state cookie use separate check/log + functions. + + Check more ioctl() calls for failure. + + systrace_{read,write} now return the number of bytes read/written + or -1 on error. + +2005-11-13 14:51 millert + + * env.c: Add more environment variables to remove; from gentoo + linux Add some comments about what bad env variables go to what + (more to do) + +2005-11-11 17:23 millert + + * sudo.c, sudo_edit.c: Move sudo_end{gr,pw}ent() until just before + the exec since they free up our cached copy of the passwd + structs, including sudo_user and sudo_runas. Fixes a + use-after-free bug. + +2005-11-11 17:19 millert + + * visudo.c: Close all fd's before executing editor. + +2005-11-11 17:17 millert + + * sudo.c: Enable malloc debugging on OpenBSD when SUDO_DEVEL is + set. + +2005-11-11 11:22 millert + + * check.c: Fix fd leak when lecture file option is enabled. From + Jerry Brown + +2005-11-07 11:02 millert + + * env.c: Add PERLLIB, PERL5LIB and PERL5OPT to the default list of + environment variables to remove. From Charles Morris + +2005-11-01 13:24 millert + + * env.c: add JAVA_TOOL_OPTIONS to initial_badenv_table for java 5 + +2005-10-27 20:35 millert + + * env.c: add PS4 and SHELLOPTS to initial_badenv_table for bash + +2005-08-14 20:32 millert + + * sudoers.pod: Fix typo; Toby Peterson + +2005-08-02 09:57 millert + + * tsgetgrpw.c: Make return buffers static so they don't get + clobbered + +2005-07-27 21:14 millert + + * auth/securid5.c: Fix securid5 authentication, was not checking + for ACM_OK. Also add default cases for the two switch()es. + Problem noted by ccon at worldbank + +2005-06-26 20:10 millert + + * ldap.c: Remove ncat() in favor of just counting bytes and + pre-allocating what is needed. + +2005-06-26 19:44 millert + + * ldap.c: Fix up some comments Add missing fclose() for the + rootbinddn case + +2005-06-26 19:38 millert + + * ldap.c: align struct ldap_config + +2005-06-26 19:37 millert + + * ldap.c: use LINE_MAX for max conf file line size + +2005-06-26 18:36 millert + + * pathnames.h.in: add _PATH_LDAP_SECRET + +2005-06-26 18:36 millert + + * README.LDAP: Mention rootbinddn Give example ou=SUDOers container + +2005-06-25 18:03 millert + + * configure, INSTALL, configure.in, ldap.c: Support rootbinddn in + ldap.conf + +2005-06-25 17:46 millert + + * env.c, sudo.pod, sudoers.pod: Preserve DISPLAY environment + variable by default. + +2005-06-25 16:39 millert + + * acsite.m4, configure: set need_lib_prefix=no for all cases; this + is safe for LD_PRELOAD + +2005-06-25 16:15 millert + + * acsite.m4, configure: set need_version=no for all cases; this is + safe for LD_PRELOAD + +2005-06-25 14:45 millert + + * aclocal.m4: typo + +2005-06-25 14:33 millert + + * configure, configure.in: Add dragonfly + +2005-06-25 14:29 millert + + * auth/pam.c: Fix call to pam_end() when pam_open_session() fails. + +2005-06-25 14:21 millert + + * configure: regen + +2005-06-25 14:20 millert + + * acsite.m4: rebuild acsite.m4 from libtool 1.9f libtool.m4 + ltoptions.m4 ltsugar.m4 ltversion.m4 + +2005-06-25 14:08 millert + + * config.guess, config.sub, ltmain.sh: merge in local changes: + config.guess: o better openbsd support config.sub: o hiuxmpp + support ltmain.sh o remove requirement that libs must begin with + "lib" o don't print a bunch of crap about library installs o + don't run ldconfig + +2005-06-25 14:05 millert + + * config.guess, config.sub, ltmain.sh: libtool 1.9f + +2005-06-25 14:04 millert + + * configure.in: Update with autoupdate and make minor changes for + libtool 1.9f + +2005-06-22 23:19 millert + + * parse.c: don't call sudo_ldap_display_cmnd if ldap not setup + +2005-06-22 23:04 millert + + * check.c, compat.h, fileops.c, gettime.c, sudo_edit.c, visudo.c, + emul/timespec.h: Move declatation of struct timespec to its own + include files for systems without it since it needs time_t + defined. + +2005-06-22 22:57 millert + + * ldap.c: Don't set safe_cmnd for the "sudo ALL" case. + +2005-05-27 01:59 millert + + * auth/pam.c: Call pam_open_session() and pam_close_session() to + give pam_limits a chance to run. Idea from Karel Zak. + +2005-04-24 19:24 millert + + * check.c, sudo.c: Add explicit cast from mode_t -> u_int in printf + to silence warnings on Solaris + +2005-04-24 19:22 millert + + * parse.c: include grp.h to silence a warning on Solaris + +2005-04-23 15:10 millert + + * parse.c: Fix printing of += and -= defaults. + +2005-04-17 01:21 millert + + * mon_systrace.c: Sanity check number of syscall args with argsize. + Not really needed but a little paranoia never hurts. + +2005-04-17 01:18 millert + + * mon_systrace.c, mon_systrace.h: Don't do pointer arithmetic on + void * Use int, not size_t/ssize_t for systrace lengths (since it + uses int) + +2005-04-16 03:14 millert + + * mon_systrace.c: Add some memsets for paranoia Fix namespace + collsion w/ error Check rval of decode_args() and update_env() + Remove improper setting of validated variable + +2005-04-11 21:37 millert + + * parse.c, sudo.c, sudo.h: In -l mode, only check local sudoers + file if def_ignore_sudoers is not set and call LDAP versions from + display_privs() and display_cmnd() instead of directly from + main(). Because of this we need to defer closing the ldap + connection until after -l processing has ocurred and we must pass + in the ldap pointer to display_privs() and display_cmnd(). + +2005-04-11 21:33 millert + + * ldap.c: Reorganize LDAP code to better match normal sudoers + parsing. Instead of storing strings for later printing in -l + mode we do another query since the authenticating user and the + user being listed may not be the same (the new -U flag). Also + add support for "sudo -l command". + + There is still a fair bit if duplicated code that can probably be + refactored. + +2005-04-11 00:37 millert + + * ldap.c: Replace pass variable with do_netgr for better + readability. + +2005-04-10 23:49 millert + + * ldap.c: use DPRINTF macro + +2005-04-10 23:18 millert + + * ldap.c: estrdup, not strdup + +2005-04-10 17:44 millert + + * parse.c: Add macro to test if the tag changed to improve + readability. + +2005-04-10 17:40 millert + + * parse.c: Avoid printing defaults header if there are no defaults + to print... + +2005-04-10 15:29 millert + + * glob.c: Fix a warning on systems without strlcpy(). + +2005-04-10 13:32 millert + + * pwutil.c: Use macros where possible for sudo_grdup() like + sudo_pwdup(). + +2005-04-08 17:04 millert + + * utimes.c: It is possible for tv_usec to hold >= 1000000 usecs so + add in tv_usec / 1000000. + +2005-03-29 23:38 millert + + * auth/kerb5.c: The component in krb5_principal_get_comp_string() + should be 1, not 0 for Heimdal. From Alex Plotnick. + +2005-03-29 09:29 millert + + * alias.c, alloc.c, check.c, defaults.c, find_path.c, gram.c, + gram.y, interfaces.c, ldap.c, logging.c, match.c, mon_systrace.c, + pwutil.c, redblack.c, sudo.c, sudo.h, toke.c, toke.l, visudo.c: + Add efree() for consistency with emalloc() et al. Allows us to + rely on C89 behavior (free(NULL) is valid) even on K&R. + +2005-03-28 22:33 millert + + * parse.c, sudo.c: Move initgroups() for -U option into + display_privs() so group matching in sudoers works correctly. + +2005-03-26 21:34 millert + + * ldap.c: Removed duplicate call to ldap_unbind_s introduced along + with sudo_ldap_close. + +2005-03-26 20:01 millert + + * parse.c: Add missing space in Defaults printing + +2005-03-25 12:36 millert + + * pwutil.c: Sync sudo_pwdup with OpenBSD changes: use macros for + size computaton and string copies. + +2005-03-18 22:08 millert + + * pwutil.c: Zero old pw_passwd before replacing with version from + shadow file. + +2005-03-18 22:07 millert + + * configure, configure.in: Only attempt shadow password detection + if PAM is not being used Add shadow_* variables to make shadow + password detection more generic. + +2005-03-18 21:46 millert + + * configure.in: Use OSDEFS for os-specific -D_FOO_BAR stuff rather + than CPPFLAGS + +2005-03-12 19:27 millert + + * sudoers.pod: use a non-breaking space to avoid a double space + after e.g. + +2005-03-12 19:26 millert + + * sudo.pod: commna, not colon after e.g. + +2005-03-12 18:43 millert + + * sudo_noexec.c: Add __ variants of the exec functions. GNU libc + at least uses __execve() internally. + +2005-03-12 12:29 millert + + * indent.pro: Match reality a bit more. + +2005-03-12 12:27 millert + + * pwutil.c: Missed piece from rev. 1.6, fix sudo_getpwnam() too. + +2005-03-11 23:42 millert + + * pwutil.c: Store shadow password after making a local copy of + struct passwd in case normal and shadow routines use the same + internal buffer in libc. + +2005-03-10 20:57 millert + + * alloc.c, logging.c: Make varargs usage consistent with the rest + of the code. + +2005-03-10 10:09 millert + + * sudo_noexec.c: Wrap more of the exec family since on Linux the + others do not appear to go through the normal execve() path. + +2005-03-10 09:57 millert + + * visudo.c: make print_unused static like proto says + +2005-03-10 09:55 millert + + * glob.c: silence a warning on K&R systems + +2005-03-10 09:51 millert + + * parse.c, alias.c, error.c: make this build in K&R land + +2005-03-07 22:21 millert + + * toke.c: regen + +2005-03-05 22:46 millert + + * ldap.c: return(foo) not return foo optimize _atobool() slightly + +2005-03-05 22:40 millert + + * ldap.c: Use TRUE/FALSE + +2005-03-05 22:31 millert + + * ldap.c: Reformat to match the rest of sudo's code. + +2005-03-05 19:33 millert + + * sudo.pod: I am the primary author + +2005-02-22 22:28 millert + + * README, RUNSON, Makefile.in: The RUNSON file is toast--it + confused too many people and really isn't needed in a + configure-oriented world. + +2005-02-22 22:28 millert + + * INSTALL: alternate -> alternative + +2005-02-22 22:26 millert + + * tgetpass.c: Use TCSADRAIN instead of TCSAFLUSH since some OSes + have issues with TCSAFLUSH. + +2005-02-22 22:16 millert + + * toke.l: Allow leading blanks before Defaults and Foo_Alias + definitions + +2005-02-22 22:14 millert + + * Makefile.in: fix rules to build toke.o and gram.o in devel mode + +2005-02-20 13:00 millert + + * sudoers.pod: env_keep overrides set_logname + +2005-02-20 12:57 millert + + * env.c: Fix disabling set_logname and make env_keep override + set_logname. + +2005-02-20 12:28 millert + + * compat.h, config.h.in, configure, configure.in: No longer need + memmove() + +2005-02-20 11:48 millert + + * env.c, sudo.c: Just clean the environment once. This assumes + that any further setenv/putenv will be able to handle the fact + that we replaced environ with our own malloc'd copy but all the + implementations I've checked do. + +2005-02-15 23:16 millert + + * env.c, sudo.c: In -i mode, base the value of insert_env()'s + dupcheck flag on DID_FOO flags. Move checks for $HOME resetting + into rebuild_env() + +2005-02-13 00:33 millert + + * env.c, sudo.c: Move setting of user_path, user_shell, user_prompt + and prev_user into init_vars() since user_shell at least is + needed there. + +2005-02-12 18:51 millert + + * Makefile.in: fix devel builds + +2005-02-12 18:46 millert + + * check.c, sudo.c: Fix some printf format mismatches on error. + +2005-02-12 18:33 millert + + * configure, gram.c, toke.c: regen + +2005-02-12 17:56 millert + + * LICENSE, Makefile.binary.in, Makefile.in, aclocal.m4, alias.c, + alloc.c, check.c, closefrom.c, compat.h, configure.in, + defaults.c, defaults.h, env.c, error.c, fileops.c, find_path.c, + getprogname.c, getspwuid.c, gettime.c, goodpath.c, gram.y, + interfaces.c, interfaces.h, ldap.c, logging.c, logging.h, + match.c, mon_systrace.c, parse.c, redblack.c, redblack.h, + set_perms.c, sigaction.c, snprintf.c, strcasecmp.c, strerror.c, + strlcat.c, strlcpy.c, sudo.c, sudo.h, sudo.pod, sudo_edit.c, + sudo_noexec.c, sudoers.pod, testsudoers.c, tgetpass.c, toke.l, + utimes.c, version.h, visudo.c, visudo.pod, zero_bytes.c, + 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, auth/sudo_auth.h, + emul/utime.h: Update copyright years. + +2005-02-12 16:46 millert + + * BUGS, INSTALL, INSTALL.binary, Makefile.in, README, configure.in: + version 1.7 + +2005-02-12 16:16 millert + + * WHATSNEW: What's new in sudo 1.7, based on the 1.7 CHANGES + entries. + +2005-02-11 18:06 millert + + * compat.h, logging.h, sudo.h: Add __printflike and use it with gcc + to warn about printf-like format mismatches + +2005-02-10 00:16 millert + + * CHANGES, ChangeLog: Replaced CHANGES file with ChangeLog + generated from cvs logs + +2005-02-10 00:03 millert + + * set_perms.c: Use warning/error instead of perror/fatal. + +2005-02-09 23:13 millert + + * config.guess: Update OpenBSD section + +2005-02-09 23:10 millert + + * UPGRADE: Add upgrading noted for 1.7 + +2005-02-09 23:00 millert + + * env.c, sudo.c, sudoers.pod: Instead of zeroing out the + environment, just prune out entries based on the env_delete and + env_check lists. Base building up the new environment on the + current environment and the variables we removed initially. + +2005-02-09 22:23 millert + + * configure, configure.in, sudo.c, config.h.in: Set locale to "C" + if locales are supported, just to be safe. + +2005-02-09 22:19 millert + + * toke.c, toke.l: Cast argument to ctype functions to unsigned + char. + +2005-02-07 22:56 millert + + * env.c: correct value for DID_USER + +2005-02-07 22:55 millert + + * error.c, fnmatch.c, getcwd.c, glob.c, snprintf.c: #include + not "compat.h" + +2005-02-07 22:51 millert + + * defaults.c: Reset the environment by default. + +2005-02-07 22:50 millert + + * sudo.c: Alloc an extra slot in NewArgv. Removes the need to + malloc an new vector if execve() fails. + +2005-02-06 23:16 millert + + * INSTALL, config.h.in, configure, configure.in, sudo.c: Use + execve(2) and wrap the command in sh if we get ENOEXEC. + +2005-02-05 23:01 millert + + * sudo_noexec.c: Only include time.h on systems that lack struct + timespec which gets defind in compat.h (using time_t). + +2005-02-05 22:59 millert + + * sudo_noexec.c: Include time.h for time_t in compat.h for systems + w/o struct timespec. + +2005-02-05 22:56 millert + + * configure, compat.h, config.h.in, configure.in: use bcopy on + systems w/o memmove + +2005-02-05 22:31 millert + + * compat.h: __attribute__((__unused__)) doesn't work in gcc 2.7.2.1 + so limit its use to gcc >= 2.8. + +2005-02-05 21:21 millert + + * Makefile.in: Add explicit rule to build sudo_noexec.lo + +2005-02-05 17:56 millert + + * INSTALL.configure, Makefile.in: No longer depend on VPATH; + pointed out a bunch of missed dependencies. + +2005-02-05 13:18 millert + + * TROUBLESHOOTING: Help for PAM when account section is missing + +2005-02-05 13:01 millert + + * auth/pam.c: Give user a clue when there is a missing "account" + section in the PAM config. + +2005-02-05 10:22 millert + + * auth/pam.c: Better error handling. + +2005-02-05 09:57 millert + + * configure, config.h.in, configure.in: Move _FOO_SOURCE to + CPPFLAGS so it takes effect as early as possible. Silences a + warning about isblank() on linux. + +2005-02-04 21:49 millert + + * auth/pam.c: Fix typo (missing comma) that caused an incorrect + number of args to be passed to log_error(). + +2005-01-31 23:03 millert + + * pwutil.c: Don't try to destroy a tree we didn't create. + +2005-01-27 10:42 millert + + * alias.c, alloc.c, check.c, closefrom.c, compat.h, defaults.c, + env.c, error.c, fileops.c, find_path.c, fnmatch.c, getcwd.c, + getprogname.c, getspwuid.c, gettime.c, goodpath.c, gram.c, + gram.y, interfaces.c, ldap.c, logging.c, match.c, mon_systrace.c, + parse.c, pwutil.c, set_perms.c, sigaction.c, snprintf.c, + strcasecmp.c, strerror.c, strlcat.c, strlcpy.c, sudo.c, + sudo_edit.c, sudo_noexec.c, testsudoers.c, tgetpass.c, toke.c, + toke.l, utimes.c, visudo.c, zero_bytes.c, 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: Add __unused to + rcsids + +2005-01-21 10:34 millert + + * configure, configure.in: Fix error message when mixing invalid + auth types + +2005-01-21 10:32 millert + + * INSTALL: PAM, AIX auth, BSD auth and login_cap are now on by + default if the OS supports them. + +2005-01-21 10:29 millert + + * config.h.in, auth/sudo_auth.h: s/HAVE_AUTHENTICATE/HAVE_AIXAUTH/g + +2005-01-21 10:29 millert + + * configure.in: Better checking for conflicting authentication + methods Display the authentication methods used at the end of + configure Rename --with-authenticate -> --with-aixauth Use + --with-aixauth, --with-bsdauth, --with-pam, --with-logincap by + default on systems that support them unless disabled. Add + OSMAJOR variable that replaces old OSREV; now OSREV has full + version number + +2005-01-17 19:40 millert + + * def_data.c, def_data.in, sudo.c, sudoers.pod: s/-O/-C/ + +2005-01-14 13:35 millert + + * configure.in: Replace: test -n "$FOO" || FOO="bar" + + With: : ${FOO='bar'} + +2005-01-09 18:58 millert + + * pwutil.c, testsudoers.c, tsgetgrpw.c: Use function pointers to + only call private passwd/group routines when using a nonstandard + passwd/group file. + +2005-01-06 10:34 millert + + * CHANGES: sync + +2005-01-05 22:16 millert + + * tsgetgrpw.c: Can't use strtok() since it doesn't handle empty + fields so add getpwent()/getgrent() functions and call those. + +2005-01-05 17:29 millert + + * Makefile.in: Fix dummied out toke.c and gram.c dependencies. + +2005-01-05 17:18 millert + + * Makefile.in: Rename PARSESRCS -> GENERATED since it is only used + in the clean target Add devdir variable and use it to specify the + path to parser sources + +2005-01-05 17:17 millert + + * configure: regen + +2005-01-05 17:17 millert + + * configure.in: Add a devdir variables that defaults to $(srcdir) + and is set to . if --devel was specified. Allows for proper + dependecies building the parser. + +2005-01-05 14:50 millert + + * testsudoers.c: Add support for custom passwd/group files. + +2005-01-05 14:47 millert + + * Makefile.in: Build private copy of pwutil.o for testsudoers with + MYPW defined so it uses our own passwd/group routines. + +2005-01-05 14:46 millert + + * visudo.c: Remove sudo_*{pw,gr}* stubs and add + sudo_setspent/sudo_endspent stubs instead. We can now just use + the caching sudo_*{pw,gr}* functions in pwutil.c Add comment + about wanting to call sudo_endpwent/sudo_endgrent in cleanup() + +2005-01-05 14:44 millert + + * tsgetgrpw.c: Remove caching; we will just use what is in pwutil.c + Use global buffers for passwd/group structs Rename functions from + sudo_* to my_* + +2005-01-05 14:43 millert + + * logging.c, sudo.c: g/c pwcache_init/pwcache_destroy + +2005-01-05 14:42 millert + + * sudo.h: Undo last commit and add sudo_setspent and sudo_endspent + instead. + +2005-01-05 14:41 millert + + * getspwuid.c, pwutil.c: Move all but the shadow stuff from + getspwuid.c to pwutil.c and pwcache_get and pwcache_put as they + are no longer needed. Also add preprocessor magic to use private + versions of the passwd and group routines if MYPW is defined (for + use by testsudoers). + +2005-01-04 22:40 millert + + * tsgetgrpw.c: zero out struct passwd/group before filling it in so + if there are fields we don't handle they end up as 0. + +2005-01-04 20:10 millert + + * logging.c, sudo.c, sudo.h, testsudoers.c, visudo.c: Adapt to + pwutil.c + +2005-01-04 20:09 millert + + * Makefile.in: Add tsgetgrpw.c and pwutil.c Rename the *OBJ + variables for better readability. + +2005-01-04 20:08 millert + + * tsgetgrpw.c: Passwd and group lookup routines for testsudoers + that support alternate passwd and group files. + +2005-01-04 20:07 millert + + * getspwuid.c, pwutil.c: Split off pw/gr cache and dup code into + its own file. This allows visudo and testsudoers to use the + pw/gr cache too. + +2005-01-01 19:31 millert + + * parse.c: Print Defaults info in "sudo -l" output and wrap lines + based on the terminal width. + +2005-01-01 12:41 millert + + * match.c, visudo.c, testsudoers.c: Only check group vector in + usergr_matches() if we are matching the invoking or list user. + Always check the group members, even if there was a group vector. + +2004-12-17 17:24 millert + + * LICENSE, Makefile.in, fnmatch.3: No longer bundle fnmatch.3 + +2004-12-17 13:12 millert + + * CHANGES, TODO: checkpoint + +2004-12-16 14:20 millert + + * sudo.c: sort usage + +2004-12-16 14:20 millert + + * sudo.pod: Sort command line options + +2004-12-16 13:33 millert + + * def_data.c, def_data.h, def_data.in, defaults.c, logging.c, + sudo.c, sudo.pod, sudoers.pod: Add closefrom sudoers option to + start closing at a point other than 3. Add closefrom_override + sudoers option and -C sudo flag to allow the user to specify a + different closefrom starting point. + +2004-12-16 13:25 millert + + * pathnames.h.in: Add _PATH_DEVNULL for those without it. + +2004-12-15 22:55 millert + + * LICENSE: no more UCB strcasecmp + +2004-12-15 22:54 millert + + * strcasecmp.c: replace BSD licensed one with version derived from + pdksh + +2004-12-09 21:07 millert + + * sudo.c: Fix last commit. + +2004-12-09 19:26 millert + + * sudo.c: Make sure stdin, stdout and stderr are open and dup them + to /dev/null if not. + +2004-12-03 13:57 millert + + * ldap.c, mon_systrace.c, sudo.c, sudo.h: add sudo_ldap_close + +2004-12-03 13:52 millert + + * fileops.c, gettime.c, sudo.c, sudo_edit.c, utimes.c, visudo.c: + Use TIME_WITH_SYS_TIME + +2004-12-03 13:48 millert + + * configure, configure.in, config.h.in: Add TIME_WITH_SYS_TIME_H + +2004-12-02 11:18 millert + + * env.c: Add missing braces to avoid DYLD_FORCE_FLAT_NAMESPACE + being set unconditionally on darwin. From Toby Peterson. + +2004-12-02 10:40 millert + + * getspwuid.c: Check rbinsert() return value. In the case of faked + up entries there is usually a negative response cached that we + need to overwrite. + + In pwfree() don't try to zero out a NULL pw_passwd pointer. + +2004-12-02 09:53 millert + + * mon_systrace.c: Use the double fork trick to avoid the monitor + process being waited for by the main program run through sudo. + +2004-11-29 12:52 millert + + * sudo.c: Call initgroups() in -U mode so group matches work + normally. + +2004-11-29 12:34 millert + + * def_data.h, mkdefaults: Don't print a trailing comma for the last + entry in enum def_tupple + +2004-11-28 16:08 millert + + * sudoers.cat, sudoers.man.in, sudoers.pod: Mention values when + lecture, listpw and verifypw are used in boolean context. + +2004-11-28 16:05 millert + + * def_data.c, def_data.in: verifypw when used in a boolean TRUE + context should be "all", not "any". + +2004-11-26 14:21 millert + + * def_data.in, defaults.c: Allow tuples that can be used as + booleans to be used as boolean TRUE. In this case the 2nd + possible value of the tuple is used for TRUE. + +2004-11-25 12:23 millert + + * configure, configure.in: Correct the test for 2-parameter + timespecsub + +2004-11-25 12:20 millert + + * sudo.h: Add strub struct definitions for passwd, timeval and + timespec + +2004-11-25 12:09 millert + + * configure, configure.in, config.h.in, sudo_edit.c, visudo.c: Add + check for 2-argument form of timespecsub (FreeBSD and BSD/OS) and + fix a typo in the gettimeofday check. + +2004-11-24 16:44 millert + + * match.c, testsudoers.c: Deal with user_stat being NULL as it is + for visudo and testsudoers. + +2004-11-24 16:31 millert + + * parse.c, sudo.c, sudo.cat, sudo.h, sudo.man.in, sudo.pod: Add -U + option to use in conjunction with -l instead of -u. Add support + for "sudo -l command" to test a specific command. + +2004-11-24 16:28 millert + + * gram.c, gram.y, sudo.c: Set safe_cmnd after sudoers_lookup() if + it has not been set. Previously it was set by sudo "ALL" in the + parser but at that point the fully-qualified pathname has not yet + been found. + +2004-11-23 18:18 millert + + * parse.c, testsudoers.c: Correctly handle multiple privileges per + userspec and runas inheritence. + +2004-11-21 14:09 millert + + * defaults.c: Zero out sd_un for each entry in sudo_defs_table in + init_defaults. + +2004-11-19 18:04 millert + + * toke.c, toke.l: make per-command defaults work with sudoedit + +2004-11-19 18:00 millert + + * ldap.c, parse.c, sudo.c, sudo.h: Remove the FLAG_NOPASS, + FLAG_NOEXEC and FLAG_MONITOR flags. Instead, we just set the + approriate defaults variable. + +2004-11-19 17:09 millert + + * sample.sudoers, sudoers.cat, sudoers.man.in, sudoers.pod: + Document per-command Defaults. + +2004-11-19 16:35 millert + + * defaults.c, defaults.h, gram.c, gram.h, gram.y, mon_systrace.c, + sudo.c, testsudoers.c, toke.c, toke.l, visudo.c: Add support for + command-specific Defaults entries. E.g. + Defaults!/usr/bin/vi noexec + +2004-11-19 15:03 millert + + * defaults.c, match.c, parse.c, parse.h, testsudoers.c: Change an + occurence of user_matches() -> runas_matches() missed previously + runas_matches(), host_matches() and cmnd_matches() only really + need to pass in a list of members. user_matches() still needs to + pass in a passwd struct because of "sudo -l" + +2004-11-19 14:46 millert + + * parse.c: Check def_authenticate, def_noexec and def_monitor when + setting return flags. XXX May be better to just set the defaults + directly and get rid of those flags. + +2004-11-19 13:39 millert + + * alias.c, alloc.c, check.c, closefrom.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, ldap.c, logging.c, match.c, + mon_systrace.c, parse.c, redblack.c, set_perms.c, snprintf.c, + strcasecmp.c, strerror.c, strlcat.c, strlcpy.c, sudo.c, + sudo_edit.c, sudo_noexec.c, testsudoers.c, tgetpass.c, toke.c, + toke.l, utimes.c, visudo.c, zero_bytes.c, 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: Use: #include + Not: #include "config.h" That way we get the correct + config.h when build dir != src dir + +2004-11-19 13:30 millert + + * Makefile.in: Back out part of rev 1.263; fix -I order + +2004-11-19 13:12 millert + + * toke.c, toke.l: More robust parsing if #include; could be much + better still. + +2004-11-19 12:55 millert + + * sudo_edit.c, visudo.c: Make arg splitting in visudo and sudoedit + consistent. + +2004-11-19 12:35 millert + + * Makefile.in, alias.c, gram.c, gram.y, parse.h: Split alias + routines out into their own file. + +2004-11-19 12:32 millert + + * error.h: __attribute__ is already defined in compat.h + +2004-11-19 12:30 millert + + * visudo.c: quit() should not be __noreturn__ as it is non-void on + some platforms. + +2004-11-19 12:24 millert + + * auth/: fwtk.c, rfc1938.c, securid.c, securid5.c: Add local + error/warning functions like err/warn but that call an additional + cleanup routine in the error case. This means we no longer need + to compile a special version of alloc.o for visudo. + +2004-11-19 11:54 millert + + * parse.h: Clarify comments about the data structures + +2004-11-18 15:28 millert + + * visudo.c: Add support for VISUAL and EDITOR containing command + line args. If env_editor is not set any args in VISUAL and + EDITOR are ignored. Arguments are also now supported in + def_editor. + +2004-11-17 14:25 millert + + * parse.h: alias_matches() is no more + +2004-11-17 14:09 millert + + * CHANGES, TODO: sync + +2004-11-17 13:19 millert + + * Makefile.in: When regenerating the parser, don't replace gram.h + unless it has changed. + +2004-11-17 11:56 millert + + * Makefile.in: remove Makefile.binary for distclean + +2004-11-17 11:18 millert + + * env.c: Preserve KRB5CCNAME in zero_env() and add a paranoia check + to make sure we can't overflow new_env. + +2004-11-17 10:33 millert + + * sudo_edit.c: paranoia when stripping trailing slashes from + tempdir. + +2004-11-16 19:00 millert + + * sudo.c: Set user_ngroups to 0 if getgroups() returns an error. + +2004-11-16 18:59 millert + + * configure, configure.in, config.h.in, sudo.c: Add configure check + for getgroups() + +2004-11-16 18:55 millert + + * ldap.c: Use supplementary group vector in struct sudo_user. + +2004-11-16 18:40 millert + + * match.c: Only do string comparisons on the group members if there + is no supplemental group list. + +2004-11-16 16:10 millert + + * CHANGES, TODO: sync + +2004-11-16 15:54 millert + + * sudo_edit.c: On Digital UNIX _PATH_VAR_TMP doesn't end with a + trailing slash so chop off any trailing slashes we see and add an + explicit one. + +2004-11-16 12:02 millert + + * match.c: remove bogus XXX comment + +2004-11-16 11:10 millert + + * match.c: Get rid of alias_matches and correctly fall through to + the non-alias cases when there is no alias with the specified + name. + +2004-11-16 10:47 millert + + * getspwuid.c: Cache non-existent passwd/group entries too. + +2004-11-16 10:45 millert + + * gram.c: regen + +2004-11-15 23:32 millert + + * getspwuid.c: fix typo + +2004-11-15 23:24 millert + + * check.c, getspwuid.c, glob.c, ldap.c, logging.c, match.c, + mon_systrace.h, sudo.c, sudo.h, testsudoers.c, visudo.c: + Implement group caching and use the passwd and group caches + throughout. + +2004-11-15 14:43 millert + + * match.c: Properly negate the return value of alias_matches() when + appropriate. + +2004-11-15 14:38 millert + + * match.c: Make hostname_matches() return TRUE for a match, else + FALSE like the caller expects. + +2004-11-15 13:24 millert + + * Makefile.in: Add missing dependencies on gram.h + +2004-11-15 13:06 millert + + * match.c: Use runas_matches in alias_matches() now that we have + it. + +2004-11-15 13:00 millert + + * parse.c, parse.h: Expand aliases in "sudo -l" mode + +2004-11-15 12:33 millert + + * gram.y, match.c: Use ALIAS for the member type when storing an + alias instead of HOSTALIAS/RUNASALIAS/CMNDALIAS/USERALIAS since + match.c relies on the more generic type. Expand runas_matches + instead of calling user_matches() inside of it since + user_matches() looks up USERALIASes, not RUNASALIASes. + +2004-11-15 12:05 millert + + * CHANGES, getspwuid.c: Paranoia; zero out pw_passwd before freeing + passwd entry. + +2004-11-15 10:53 millert + + * LICENSE, Makefile.in, alloc.c, check.c, config.h.in, configure, + configure.in, err.c, error.c, error.h, defaults.c, env.c, + find_path.c, interfaces.c, logging.c, mon_systrace.c, sudo.c, + sudo.h, sudo_edit.c, testsudoers.c, visudo.c, emul/err.h: Add + local error/warning functions like err/warn but that call an + additional cleanup routine in the error case. This means we no + longer need to compile a special version of alloc.o for visudo. + +2004-11-15 09:59 millert + + * match.c: Use userpw_matches() to compare usernames, not strcmp(), + since the latter checks for "#uid". + +2004-11-15 09:53 millert + + * getspwuid.c, mon_systrace.c, mon_systrace.h, sudo.c: Cache passwd + db entries in 2 reb-black trees; one indexed by uid, the other by + user name. The data returned from the cache should be considered + read-only and is destroyed by sudo_endpwent(). + +2004-11-15 09:50 millert + + * match.c: add cast to uid_t + +2004-11-15 09:49 millert + + * gram.y: missing free in alias_destroy + +2004-11-15 09:49 millert + + * redblack.c: Can't use rbapply() for rbdestroy since the + destructor is passed a data pointer, not a node pointer. + +2004-11-14 23:06 millert + + * getspwuid.c, logging.c, sudo.c, sudo.h: Create and use private + versions of setpwent() and endpwent() that set/end the shadow + password file too. + +2004-11-14 22:55 millert + + * gram.c, gram.h, gram.y, match.c, parse.h, testsudoers.c, + visudo.c: Store aliases in a red-black tree. + +2004-11-14 22:52 millert + + * Makefile.in, redblack.c, redblack.h: red-black tree + implementation + +2004-11-14 22:37 millert + + * visudo.c: Edit all sudoers file if there were unused or undefined + aliases and we are in strict mode. + +2004-11-12 11:19 millert + + * CHANGES, def_data.c, def_data.h, def_data.in, defaults.c, env.c, + find_path.c, sudoers.cat, sudoers.man.in, sudoers.pod, visudo.c: + Bring back the "secure_path" Defaults option now that Defaults + take effect before the path is searched. + +2004-11-11 12:22 millert + + * logging.c, parse.c: A user can always list their own entries, + even with -u. Better error message when failing to list another + user's entries. + +2004-11-11 12:12 millert + + * parse.c, sudo.c, sudo.h: The syntax to list another user's + entries is now "-u otheruser -l". Only root or users with sudo + "ALL" may list other user's entries. + +2004-11-11 11:30 millert + + * sudo.cat, sudo.man.in, sudo.pod: Update env variable info in + SECURITY NOTES + +2004-11-11 11:25 millert + + * env.c: strip CDPATH too + +2004-11-11 11:20 millert + + * env.c: strip exported bash functions from the environment. + +2004-10-27 12:16 millert + + * sudo.c: Only reset sudo_user.pw based on SUDO_USER environment + variables for real commands and sudoedit. This avoids a + confusing message when a user tries "sudo -l" or "sudo -v" and is + denied. + +2004-10-27 12:06 millert + + * gram.c, gram.y, parse.h: Extend LIST_APPEND to deal with + appending lists too + +2004-10-26 18:39 millert + + * logging.c: Convert some bitwise AND to ISSET + +2004-10-26 18:29 millert + + * lex.yy.c, toke.c: toke.c replaces lex.yy.c + +2004-10-26 18:29 millert + + * CHANGES, TODO: sync + +2004-10-26 18:28 millert + + * BUGS: new parser fixes most of the outstanding bugs + +2004-10-26 18:27 millert + + * configure: regen + +2004-10-26 18:26 millert + + * visudo.c: Rework for the new parser. Now checks for unused + aliases in sudoers. + +2004-10-26 18:25 millert + + * testsudoers.c: Rewrite for the new parser. Now supports a -d + flag (dump) and adds a -h flag (host). It now defaults to the + local hostname unless otherwise specified. + +2004-10-26 18:23 millert + + * sudo.h: Add new prototypes. Remove NOMATCH/UNSPEC (now in + parse.h) + +2004-10-26 18:22 millert + + * sudo.c: Update for new parse. We now call find_path() *after* we + have updated the global defaults based on sudoers. Also adds + support for listing other user's privs if you are root. + +2004-10-26 18:21 millert + + * mon_systrace.c: Working LDAP support; also remove a now-unneeded + rewind(). + +2004-10-26 18:20 millert + + * logging.c, logging.h: Add NO_STDERR flag. + +2004-10-26 18:19 millert + + * ldap.c: Split sudo_ldap_check() into three pieces: + sudo_ldap_open(), udo_ldap_update_defaults() and + sudo_ldap_check(). This allows us to connecto to LDAP, apply the + default options, find the command in the user's path, and then + check whether the user is allowed to run it. The important thing + here is that the default runas user may be specified as a default + option and that needs to be set before we search for the command. + +2004-10-26 18:17 millert + + * ldap.c: Add casts to unsigned char for isspace() to quiet a gcc + warning. + +2004-10-26 18:16 millert + + * defaults.h: Add prototype for update_defaults() + +2004-10-26 18:16 millert + + * defaults.c: Don't warn about line numbers now that we operate on + a set of data structures (or LDAP) and not a file. + +2004-10-26 18:15 millert + + * config.h.in: No long use lsearch() + +2004-10-26 18:14 millert + + * Makefile.in: Update for new and changed file names. + +2004-10-26 18:14 millert + + * LICENSE: no more BSD lsearch.c + +2004-10-26 18:14 millert + + * match.c: foo_matches() routines now live in match.c Added + user_matches(), runas_matches(), host_matches(), cmnd_matches() + and alias_matches() that operate on the parsed sudoers file. + +2004-10-26 18:12 millert + + * parse.lex, toke.l: Move parse.lex -> toke.l Rename buffer_frob() + -> switch_buffer() WORD no longer needs to exclude '@' kill + yywrap() + +2004-10-26 18:10 millert + + * gram.c, gram.h, gram.y, parse.c, parse.h, parse.yacc, sudo.tab.h: + Rewritten parser that converts sudoers into a set of data + structures. This eliminates ordering issues and makes it + possible to apply sudoers Defaults entries before searching for + the command. + +2004-10-26 18:09 millert + + * configure.in, lsearch.c, emul/search.h: We won't be using + lsearch() any longer. + +2004-10-26 18:07 millert + + * ldap.c: sudo should not send mail if someone who runs 'sudo -l' + has no entry. + +2004-10-26 16:09 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat, + visudo.man.in: regen + +2004-10-26 16:09 millert + + * visudo.pod: Update warnings to match new visudo + +2004-10-26 16:08 millert + + * sudoers.pod: The new parser doesn't have the old ordering + constraints. + +2004-10-26 16:08 millert + + * sudo.pod: Document that -l now takes an optional username + argument + +2004-10-25 13:44 millert + + * RUNSON: AIX 5.2.0.0 works + +2004-10-25 13:38 millert + + * ldap.c: If LDAP_OPT_SUCCESS is not defined, use LDAP_SUCCESS + instead. Fixes a compilation problem with Solaris 9's native + LDAP. + + Set FLAG_MONITOR when needed. + +2004-10-23 13:32 millert + + * mon_systrace.c: Call sudo_goodpath() *after* changing the cwd to + match the traced process. Fixes relative paths. + +2004-10-21 12:31 millert + + * testsudoers.c: Kill set_perms() stub--it is no longer needed. + +2004-10-13 12:52 millert + + * sudoers.cat, sudoers.man.in, sudoers.pod: stay_setuid now + requires set_reuid() or setresuid() + +2004-10-13 12:46 millert + + * INSTALL, PORTING, TROUBLESHOOTING, config.h.in, configure, + configure.in, set_perms.c, sudo.c, sudo.h: Kill use of POSIX + saved uids; they aren't worth bothering with. + +2004-10-07 16:23 millert + + * glob.c: remove call to issetugid() + +2004-10-07 14:57 millert + + * sudoers.cat, sudoers.man.in, sudoers.pod: Remove warning about + wildcards. Now that we use glob() the bug is fixed. + +2004-10-07 14:52 millert + + * parse.c: Use glob(3) instead of fnmatch(3) for matching pathnames + and stat each result that matches the basename of the user's + command. This makes "cd /usr/bin ; sudo ./blah" work when + sudoers allows /usr/bin/blah. Fixes bug #143. + +2004-10-07 14:27 millert + + * configure, configure.in, config.h.in: Define HAVE_EXTENDED_GLOB + for extended glob (GLOB_TILDE and GLOB_BRACE) + +2004-10-07 12:59 millert + + * config.h.in, configure, configure.in: Check for a glob() that + supports GLOB_BRACE and GLOB_TILDE + +2004-10-07 12:51 millert + + * LICENSE: reference glob + +2004-10-07 12:50 millert + + * glob.c, emul/glob.h: 4.4BSD glob(3) with fixes from OpenBSD and + some unneeded extensions removed. + +2004-10-05 17:26 millert + + * mon_systrace.c: Just return if STRIOCINJECT or STRIOCREPLACE + fail. It probably means we are out of space in the stack gap... + +2004-10-05 17:20 millert + + * CHANGES: sync + +2004-10-05 16:53 millert + + * mon_systrace.c: Take a stab at ldap sudoers support here. + +2004-10-05 15:13 millert + + * mon_systrace.c, mon_systrace.h: Detach from tracee on SIGHUP, + SIGINT and SIGTERM. Now "sudo reboot" doesn't cause reboot to + inadvertanly kill itself. + +2004-10-05 14:21 millert + + * mon_systrace.c: put "monitor" in the proctitle, not "systrace" + +2004-10-05 14:15 millert + + * mon_systrace.c: When modifying the environment, don't replace + envp when we can get away with just rewriting pointers in the + traced process. + +2004-10-05 13:46 millert + + * mon_systrace.c, mon_systrace.h: Add environment updating via + STRIOCINJECT (if available). + +2004-10-05 10:22 millert + + * sudoers.cat, sudoers.man.in: regen + +2004-10-04 16:15 millert + + * lex.yy.c: regen + +2004-10-04 16:15 millert + + * parse.lex: Fix bug introduced in unput() removal; want yyless(0) + not yyless(1) + +2004-10-04 12:09 millert + + * mon_systrace.c: Include file is now mon_systrace.h + +2004-10-04 12:07 millert + + * Makefile.in, configure, configure.in, def_data.c, def_data.h, + def_data.in, lex.yy.c, parse.c, parse.h, parse.lex, parse.yacc, + sudo.c, sudo.h, sudo.tab.h, sudoers.pod: No longer call it + tracing, it is now "monitoring" which should be more a obvious + name to non-hackers. + +2004-10-01 15:06 millert + + * mon_systrace.c, mon_systrace.h: Fix some XXX + +2004-10-01 14:30 millert + + * mon_systrace.c, mon_systrace.h: No need to include syscall.h, use + 1024 as the max # of entries (the max that systrace(4) allows). + + Only need to use SYSTR_POLICY_ASSIGN once + + Change check_syscall() -> find_handler() and have it return the + handler instead of just running it. We need this since handler + now have two parts: one part that generates and answer and + another that gets called after the answer is accepted (to do + logging). + + Add some missing check_exec for emul execv + +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. + +2004-10-01 10:47 millert + + * config.h.in: Add missing HAVE_LINUX_SYSTRACE_H + +2004-09-30 20:46 millert + + * Makefile.in: add trace_systrace.o dependency + +2004-09-30 19:00 millert + + * configure, configure.in: Also look for systrace.h in + /usr/include/linux + +2004-09-30 18:27 millert + + * mon_systrace.c, mon_systrace.h: Move all struct defs and + prototypes into trace_systrace.h and mark all but + systace_attach() static. + +2004-09-30 18:14 millert + + * mon_systrace.c, mon_systrace.h: Add support for tracing + emulations. At the moment, all emulations are compiled in. It + might make sense to #ifdef them in the future, though this + impeeds readability. + +2004-09-30 17:07 millert + + * Makefile.in, configure.in, configure: rename systrace.c -> + trace_systrace.c + +2004-09-30 15:58 millert + + * parse.yacc: Allow this to build with a K&R compiler again + +2004-09-30 13:58 millert + + * TODO: sync + +2004-09-30 13:55 millert + + * sudo.c, compat.h, visudo.c: Use __attribute__((__noreturn__)) + +2004-09-30 13:44 millert + + * visudo.c: Exit() takes a negative value to indicate it was not + called via signal. + +2004-09-30 13:25 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat, + visudo.man.in: regen + +2004-09-30 13:22 millert + + * Makefile.in, visudo.c: Define Err() and Errx() that are like + err() and errx() but call Exit() instead of exit(). Build + private copy of alloc.o for visudo that calls Err() and Errx(). + +2004-09-29 15:22 millert + + * lex.yy.c: regen + +2004-09-29 15:22 millert + + * CHANGES: sync + +2004-09-29 14:41 millert + + * visudo.c: Overhaul visudo for editing multiple files: o visudo + has been broken out into functions (more work needed here) o + each file is now edited before sudoers is re-parsed o if a + #include line is added that file will be edited too + + TODO: o cleanup temp files when exiting via err() or errx() o + continue breaking things out into separate functions + +2004-09-29 14:36 millert + + * parse.lex, sudo.c, sudo.h, testsudoers.c, visudo.c: Add keepopen + arg to open_sudoers that open_sudoers can use to indicate to the + caller that the fd should not be closed when it is done with it. + To be used by visudo to keep locked fds from being closed + prematurely (and thus losing the lock). + +2004-09-29 14:33 millert + + * parse.yacc, sudo.c: Add errorfile global that contains the name + of the file that caused the error. + +2004-09-29 14:30 millert + + * parse.lex: return COMMENT to yacc grammar for a #include line + +2004-09-29 14:29 millert + + * parse.lex: Remove us of unput() in favor of yyless() which is + cheaper. + +2004-09-29 14:28 millert + + * parse.yacc: Allow an empty sudoers file. + +2004-09-28 16:50 millert + + * mon_systrace.c: Rewind sudoers_fp now that sudoers_lookup() + doesn't do it for us. + +2004-09-28 14:37 millert + + * lex.yy.c: regen + +2004-09-28 14:36 millert + + * visudo.c: Do signal setup before calling edit_sudoers(). Don't + shadow the "quiet" global. + +2004-09-28 14:33 millert + + * visudo.c: If a sudoers file includes other files, edit those too. + Does not yes deal with creating the new includes files itself. + +2004-09-28 14:31 millert + + * testsudoers.c: init_parser now takes a path + +2004-09-28 14:31 millert + + * parse.c, parse.h, parse.lex, parse.yacc: More scaffolding for + dealing with multiple sudoers files: o init_parser() now takes a + path used to populate the sudoers global o the sudoers global is + used to print the correct file in yyerror() o when switching to + a new sudoers file, perserve old file name and line number + +2004-09-28 14:29 millert + + * Makefile.in, pathnames.h.in: Kill _PATH_SUDOERS_TMP; it is not + meaningful now that we can have multiple sudoers files. + +2004-09-28 13:52 millert + + * parse.c, sudo.c: Rewind sudoers_fp in open_sudoers() instead of + sudoers_lookup() so we start at the right file position when + reading include files. + +2004-09-27 21:04 millert + + * sudoers.pod: document #include + +2004-09-27 20:47 millert + + * lex.yy.c: regen + +2004-09-27 20:47 millert + + * parse.lex: Add max depth of 128 for the include stack to avoid + loops. + + Since yyerror() doesn't stop parsing, pass return values back to + yylex and call yyterminate() on error. + +2004-09-27 14:06 millert + + * sudoers.pod: document tracing + +2004-09-27 14:05 millert + + * sudo.pod: Mention PREVENTING SHELL ESCAPES section of sudoers man + page + +2004-09-27 12:08 millert + + * lex.yy.c: regen + +2004-09-27 12:03 millert + + * parse.lex: Add support for #include in sudoers (visudo support + TBD) + +2004-09-27 12:02 millert + + * parse.yacc: make yyerror()'s argument const + +2004-09-27 12:02 millert + + * testsudoers.c, visudo.c: Add open_sudoers() stubs. + +2004-09-27 12:01 millert + + * sudo.c, sudo.h: Rename check_sudoers() open_sudoers() and make it + return a FILE * + +2004-09-26 12:35 millert + + * BUGS, INSTALL, INSTALL.binary, Makefile.in, README, configure.in, + version.h: Crank version + +2004-09-26 12:33 millert + + * Makefile.in, sudo.psf: Better HP-UX depot construction + +2004-09-25 17:08 millert + + * mon_systrace.c: o Made children global so check_exec() can lookup + a child. o Replaced uid in struct childinfo with struct passwd * + (for runas) o new_child() now takes a parent pid so the runas + info can be inherited o Added find_child() to lookup a child by + its pid o update_child() now fills in a struct passwd o Converted + the big if/else mess in set_policy to a switch o Syscalls that + change uid are now "ask" so we get SYSTR_MSG_UGID events + +2004-09-25 17:01 millert + + * getspwuid.c: Add flag to sudo_pwdup that indicates whether or not + to lookup the shadow password. Will be used to a struct passwd + that has the shadow password already filled in. + +2004-09-25 16:58 millert + + * mon_systrace.c: add missing increment of addr in read_string() + +2004-09-25 16:15 millert + + * mon_systrace.c: Remove bogus call to update_child() and some + cosmetic fixes + +2004-09-25 16:11 millert + + * mon_systrace.c: Don't leak /dev/systrace fd to tracee Make + initialized global for simplicity If STRIOCATTACH returns EBUSY + we are already being traced Check for user_args == NULL in + setproctitle() call Add missing calls to STRIOCANSWER + +2004-09-25 13:15 millert + + * sudo.c: g/c sudo_pwdup proto + +2004-09-24 20:21 millert + + * Makefile.in, sudo.psf: Add target for building a depot file + +2004-09-24 20:07 millert + + * mon_systrace.c: trim includes + +2004-09-24 14:11 millert + + * lex.yy.c, sudo.tab.h: regen + +2004-09-24 14:10 millert + + * INSTALL: document --with-systrace + +2004-09-24 14:10 millert + + * config.h.in, configure, configure.in: Add check for setproctitle + +2004-09-24 14:09 millert + + * mon_systrace.c: pass struct str_msg_ask in to syscall checker so + it can set the error code + +2004-09-24 13:30 millert + + * mon_systrace.c: systrace(4) support for sudo. On systems with + the systrace(4) kernel facility (OpenBSD, NetBSD, Linux w/ + patches) sudo can intercept exec calls and check the exec args + against the sudoers file. In other words, sudo can now control + subcommands and shell escapes. + +2004-09-24 13:17 millert + + * sudo.c, sudo.h: Call systrace_attach() if FLAG_TRACE is set. + +2004-09-24 13:15 millert + + * parse.c, parse.h, parse.lex, parse.yacc, sudo.h: Add trace + Defaults option and TRACE/NOTRACE tags and set FLAG_TRACE + +2004-09-24 13:13 millert + + * parse.c, sudo.c: Don't close sudoers_fp, keep it open and set + close on exec flag instead. + +2004-09-24 13:11 millert + + * def_data.c, def_data.h, def_data.in: Add trace option + +2004-09-23 20:24 millert + + * Makefile.in: Add systrace + +2004-09-23 20:23 millert + + * INSTALL: SunOS /bin/sh blows up with configure + +2004-09-23 20:23 millert + + * configure, configure.in: Include sys/param.h before systrace.h + +2004-09-23 20:15 millert + + * configure: regen + +2004-09-23 20:15 millert + + * pathnames.h.in: _PATH_DEV_SYSTRACE + +2004-09-23 20:14 millert + + * configure.in: line up options in --help + +2004-09-23 20:11 millert + + * config.h.in, configure.in: Add --with-systrace + +2004-09-23 13:35 millert + + * configure: regen + +2004-09-23 13:35 millert + + * aclocal.m4, configure.in: make this work with autoconf-2.59 + +2004-09-16 12:58 millert + + * sudo_edit.c: Simplify logic around open & stat of files and do + sanity on edited file even if we lack fstat (still racable but + worth doing). + +2004-09-15 18:47 millert + + * HISTORY: Add support url + +2004-09-15 16:11 millert + + * Makefile.in: versino 1.6.8p1 + +2004-09-15 15:20 millert + + * CHANGES: more changes for 1.6.8p1 + +2004-09-15 15:18 millert + + * version.h: 1.6.8p1 + +2004-09-15 12:16 millert + + * CHANGES, sudo_edit.c: Add sanity check so we don't try to edit + something other than a regular file. + +2004-09-14 20:55 aaron + + * CHANGES: sync + +2004-09-14 20:21 aaron + + * INSTALL: document --with-ldap-conf-file + +2004-09-14 17:43 millert + + * CHANGES, ins_csops.h: political correctness strikes again + +2004-09-14 15:09 millert + + * RUNSON: sync + +2004-09-12 19:50 millert + + * Makefile.binary.in, Makefile.in: Install sudoedit man link + +2004-09-12 14:25 millert + + * INSTALL: Update PAM note and mention where HP-UX users can + download gcc binaries. + +2004-09-12 12:08 millert + + * Makefile.in: libtool wants to install stuff from .libs so fake + one up for binary installations. + +2004-09-12 11:53 millert + + * Makefile.binary.in: rm -f old sudoedit link instead of using ln + -f set LIBTOOL correctly + +2004-09-12 11:53 millert + + * Makefile.in: Deal with "uname -m" having slashes in it rm -f old + sudoedit link instead of using ln -f + +2004-09-12 10:22 millert + + * Makefile.binary, Makefile.binary.in: Makefile.binary -> + Makefile.binary.in for config.status substitution Add support for + installing noexec bits + +2004-09-12 10:21 millert + + * Makefile.in: Copy noexec bits into binary dists too No longer use + my old arch script for making binary dists + +2004-09-12 09:36 millert + + * Makefile.binary: Install sudoedit link. + +2004-09-11 12:25 millert + + * emul/utime.h: avoid __P so there is no need for compat.h to be + included + +2004-09-11 12:24 millert + + * utimes.c: Don't use HAVE_UTIME_H before including config.h. + +2004-09-10 12:31 millert + + * compat.h: Fix Solatis futimes macro + +2004-09-09 11:02 millert + + * sudo_edit.c: Rename ots -> omtim for improved readability. + +2004-09-08 14:38 millert + + * sudo_edit.c: Redo changes in revision 1.7. Don't really need to + keep the temp file open; re-opening it with the invoking user's + euid is sufficient. + +2004-09-08 14:36 millert + + * CHANGES: sync + +2004-09-08 14:35 millert + + * sudo.cat, sudo.man.in: regen + +2004-09-08 14:34 millert + + * sudo.pod: back out revision 1.70; it is no long applicable + +2004-09-08 11:57 millert + + * env.c: Let the loader initialize nep + +2004-09-08 11:49 millert + + * configure, configure.in, config.h.in: Removed unneed check for + fchown Add check for gettimeofday Move autoheader template stuff + into separate AH_TEMPLATE lines + +2004-09-08 11:48 millert + + * check.c, compat.h, fileops.c, sudo.h, sudo_edit.c, visudo.c: Use + timespec throughout. + +2004-09-08 11:47 millert + + * Makefile.in: gettime.[co] + +2004-09-08 11:47 millert + + * gettime.c: function to return the current time in a struct + timespec + +2004-09-08 10:51 millert + + * utimes.c: Not a darpa-sponsored file. + +2004-09-07 16:36 millert + + * compat.h, config.h.in, configure, configure.in: Add a check for + struct timespec and provide it for those without. + +2004-09-07 15:56 millert + + * config.h.in, configure, configure.in, sudo_edit.c: Add checks for + st_mtim and st_mtimespec and add macros for pulling the mtime sec + and nsec out of struct stat. These are used in sudo_edit() to + better tell whether or not the file has changed. + +2004-09-07 15:55 millert + + * check.c, fileops.c, sudo.h, sudo_edit.c, visudo.c: Add an extra + param to touch() for nsec + +2004-09-07 14:06 millert + + * sudo_edit.c: Call mkstemp() as the in invoking user so we don't + have to chown the file later. Only touch() the temp file if we + can do it via the file descriptor. Don't check for modification + of the temp file if we lack fstat(). Catch errors read()ing the + temp file. + +2004-09-07 14:04 millert + + * fileops.c: If path is NULL and fd == -1 return -1. + +2004-09-07 13:31 millert + + * sudo_edit.c: closefrom() is overkill, the only extra fds are the + ones we opened so just close those in the child. + +2004-09-07 13:14 millert + + * Makefile.in, aclocal.m4, check.c, compat.h, config.h.in, + configure, configure.in, fileops.c, sudo.h, sudo_edit.c, utime.c, + utimes.c, visudo.c: Use utimes() and futimes() instead of utime() + in touch(), emulating as needed. Not all systems are able to + support setting the times of an fd so touch() takes both an fd + and a file name as arguments. + +2004-09-06 21:12 aaron + + * env.c: Rare SEGV + +2004-09-06 16:46 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat, + visudo.man.in: regen + +2004-09-06 16:45 millert + + * sudo.pod, sudoers.pod, visudo.pod: Add SUPPORT section and + re-order some of the sections to match the order we use in + OpenBSD. + +2004-09-06 15:05 aaron + + * env.c: Openldap ~/.ldaprc fix + +2004-09-06 12:18 millert + + * sudo.pod: Talk about how the editor must write its changes to the + original file and not just use rename(2). + +2004-09-06 12:12 millert + + * CHANGES: sync + +2004-09-06 12:11 millert + + * sudo_edit.c: Keep the temp file open instead of re-opening after + the editor has exited. + +2004-09-06 12:10 millert + + * sample.pam: Update for current redhat/fedora core. + +2004-09-02 21:56 aaron + + * README.LDAP: tls_ examples + +2004-09-02 00:03 aaron + + * ldap.c: config tls_* options + +2004-08-29 11:39 millert + + * configure, configure.in: No need for -lcrypt when using pam. + +2004-08-26 23:57 millert + + * configure: regen + +2004-08-26 23:44 aaron + + * configure.in, ldap.c, pathnames.h.in: Allow --with-ldap-conf-file + option to override LDAP_CONF + +2004-08-26 22:08 aaron + + * ldap.c: cleanup debug message + +2004-08-26 19:29 aaron + + * README.LDAP: more config info + +2004-08-24 14:01 millert + + * TODO, find_path.c, goodpath.c, parse.c, sudo.c, sudo.h, visudo.c: + Add cmnd_base to struct sudo_user and set it in init_vars(). Add + cmnd_stat to struct sudo_user and set it in sudo_goodpath(). No + longer use gross statics in command_matches(). Also rename some + variables for improved clarity. + +2004-08-21 14:33 millert + + * INSTALL: document HP's crippled compiler deficiency. + +2004-08-21 14:25 millert + + * INSTALL: Fix some thinkos in --with-editor and --with-env-editor + descriptions. Noticed by Norihiko Murase. + +2004-08-21 14:20 millert + + * configure, configure.in: --with-noexec takes an optional PATH + argument. + +2004-08-21 14:20 millert + + * INSTALL: document --with-noexec + +2004-08-17 16:21 millert + + * RUNSON, TODO: sync + +2004-08-17 15:11 millert + + * sudo_edit.c: Better warning message when sudoedit is unable to + write to the destination file. + +2004-08-17 14:53 millert + + * sudo.cat, sudo.man.in: regen + +2004-08-17 14:53 millert + + * sudo.pod: Don't italicize the string "sudoedit" + +2004-08-16 18:45 millert + + * HISTORY: Mention GratiSoft. + +2004-08-11 14:29 millert + + * parse.yacc: Reset used_runas to FALSE when re-intializing the + parser. + +2004-08-09 19:04 millert + + * config.guess: Correct OpenBSD mips support + +2004-08-09 17:28 millert + + * config.guess: Add OpenBSD/mips + +2004-08-06 23:43 aaron + + * README.LDAP: More behavior notes + +2004-08-06 23:36 aaron + + * README.LDAP: Updates on current behavior + +2004-08-06 19:56 millert + + * sudo.pod, sudoers.pod: =back does not take an indentlevel (makes + no difference to formatted files). + +2004-08-06 19:48 millert + + * CHANGES: new + +2004-08-06 19:42 millert + + * sudo.c: Consistency. Use same error for bad -u #uid when + targetpw is set as we do when a bad -u username is specified. + +2004-08-06 19:33 millert + + * TODO: Add checksum idea from Steve Mancini + +2004-08-06 19:32 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in: regen + +2004-08-06 19:31 millert + + * sudo.pod, sudoers.pod: Document the restriction on uids specified + via -u when targetpw is set. + +2004-08-06 19:24 millert + + * sudo.c: Error out when targetpw is enabled and sudo is run with + -u #uid but #uid does not exist in the passwd database. We can't + do target authentication when the target is not in passwd! + +2004-08-05 21:16 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in: regen + +2004-08-05 21:14 millert + + * TODO: Some more todo for the next release. + +2004-08-05 21:13 millert + + * INSTALL: Make it clear that PAM should be used for DCE support + when possible. + +2004-08-05 21:13 millert + + * sudoers.pod: o Document problems with wildcards and relative + paths. o Make the order requirements more prominent. o Change a + "set" to "reset" for clarity. + +2004-08-05 14:29 millert + + * sudo.pod: Mention --with-secure-path, not SECURE_PATH. + +2004-08-02 22:34 aaron + + * ldap.c: reflect changes to parse.c + +2004-08-02 14:44 millert + + * parse.c, parse.h, parse.yacc, testsudoers.c, visudo.c: Don't pass + user_cmnd and user_args to command_matches(), just use the + globals there. Since we keep state with statics anyway it is + misleading to pretend that passing in different cmnd and + cmnd_args will work. + +2004-08-02 14:40 millert + + * parse.c: Fix a bug introduced in rev. 1.149. When checking for + pseudo-commands check for a '/' anywhere in cmnd, not just the + first character. + +2004-07-30 23:07 aaron + + * sudo.man.in, sudo.pod: Clarification thanks to Olivier Blin + + +2004-07-30 22:41 aaron + + * sudoers.man.in, sudoers.pod: Add ignore_local_sudoers + +2004-07-30 22:06 aaron + + * README.LDAP: Sun One schema definition by + Andreas.Bussjaeger@t-systems.com and janth@moldung.no + +2004-07-29 11:57 millert + + * CHANGES: typo + +2004-07-23 16:44 millert + + * CHANGES: sync + +2004-07-23 16:43 millert + + * parse.c: Parse sudoers file as PERM_RUNAS not PERM_ROOT and + remove a useless PERM_SUDOERS. Restore to PERM_ROOT upon exit of + the parse. + +2004-07-08 10:20 millert + + * CHANGES: PAM change + +2004-07-07 21:04 aaron + + * ldap.c: Better debugging of ALL command + +2004-07-07 20:15 millert + + * parse.c: When matching for "sudoedit" in sudoers check both the + command the user typed *and* the command that is listed in the + sudoers entry. + +2004-07-04 19:59 aaron + + * ldap.c: Added !command feature + +2004-06-28 10:51 millert + + * auth/pam.c: Use pam_acct_mgmt() to check for disabled accounts; + Brian Farrell + +2004-06-10 23:11 millert + + * LICENSE: License is ISC-style, not BSD-style + +2004-06-10 20:58 millert + + * CHANGES: sync + +2004-06-10 16:54 millert + + * sudo.man.in, sudo.cat: regen + +2004-06-10 16:53 millert + + * sudo.pod: o Update some out of date bits to reality o Change the + shell promt in examples to bourne-shell style o Clarify some + details o Add a CAVEAT about "sudo cd /foo" + +2004-06-10 16:19 millert + + * check.c: Don't ask for a password if invoking user == target + user. + +2004-06-10 12:32 millert + + * sudo.c: typo in comment + +2004-06-08 19:20 millert + + * sudoers.man.in, sudoers.cat: regen + +2004-06-08 19:19 millert + + * sudoers.pod: Expand on NOEXEC a little. + +2004-06-08 16:20 millert + + * TODO: sync + +2004-06-08 15:58 millert + + * visudo.man.in, visudo.cat: regen + +2004-06-08 15:55 millert + + * CHANGES, parse.yacc, visudo.c, visudo.pod: Add a check in visudo + for runas_default being set after it has already been used. + +2004-06-08 13:53 millert + + * parse.yacc: Add a MATCHED macro for testing whether foo_matches + has been set to TRUE or FALSE. This is more readable than + checking for >=0 or < 0. Doesn't change the actual code + generated. + +2004-06-06 20:11 millert + + * sudoers.man.in, sudoers.cat: regen + +2004-06-06 20:07 millert + + * sudoers, sudoers.pod: Correct description of where Defaults specs + should go. + +2004-06-06 20:02 millert + + * find_path.c, ldap.c, logging.h, testsudoers.c, visudo.c, + auth/bsdauth.c, auth/kerb5.c, auth/pam.c: update (c) year + +2004-06-06 19:58 millert + + * check.c, compat.h, defaults.c, env.c, find_path.c, getcwd.c, + ldap.c, logging.h, parse.c, parse.yacc, sudo.c, testsudoers.c, + tgetpass.c, visudo.c, auth/bsdauth.c, auth/kerb5.c, auth/pam.c: + Remove trailing spaces, no actual code changes. + +2004-06-06 16:22 millert + + * parse.yacc: Fix a >=0 that should be <0 that was improperly + converted when UNSPEC was added. + +2004-06-06 15:54 millert + + * parse.yacc: Add do {} while(0) around pop macro Set cmnd_matches + to UNSPEC, not NOMATCH when resetting it. + +2004-06-06 15:39 millert + + * parse.yacc: Fix pastos introduced in SETNMATCH addition. + +2004-06-05 13:55 millert + + * README.LDAP: Update for configure changes + +2004-06-05 13:42 millert + + * parse.yacc, sudo.h: Add NOMATCH and UNSPEC defines (-1 and -2 + respectively) and use these in parse.yacc. Also in parse.yacc + initialize the *_matches vars to UNSPEC and add two macros, + SETMATCH and SETNMATCH for use when setting *_matches to a value + that may be NOMATCH/UNSPEC/TRUE/FALSE. + +2004-06-05 11:17 millert + + * parse.yacc: Initialize runas to -2, not -1 since we need to be + able to distinguish between the initialized value and the value + of a non-match when passing along the runas value to multiple + commands. + + The result of this is that an unmatched runas is now set to -1, + not 0. This is required now that parse.c treats a FALSE value + for runas as being explicitly denied. + +2004-06-03 16:21 millert + + * getprogname.c, sudo.c, visudo.c: Error out if argc < 1. + +2004-06-03 12:37 millert + + * configure, configure.in: Add tests for what libs we need to link + with for ldap and for whether or not lber.h needs to be + explicitly included. + +2004-06-02 20:30 aaron + + * ldap.c: Solaris native LDAP build fix + +2004-06-01 16:56 millert + + * ldap.c: Set edn to NULL is ldap_get_dn() fails to avoid potential + use of an unset variable. + +2004-06-01 16:56 millert + + * sudo.h: Add prototype for sudo_ldap_list_matches + +2004-06-01 16:53 millert + + * compat.h, config.h.in, configure, configure.in: Better check for + dirfd macro--we now set HAVE_DIRFD for the macro version too. + Added check for dd_fd in `DIR' if no dirfd is found; this is now + used to confitionally define the dirfd macro in compat.h. + +2004-06-01 16:51 millert + + * closefrom.c: Only check /proc/$$/fd if we have the dirfd + function/macro. + +2004-06-01 15:13 millert + + * compat.h, config.h.in, configure, configure.in: Add a check for a + dirfd() function (like Linux) and add a dirfd macro in compat.h + if there is no dirfd() function or macro. + +2004-06-01 14:59 millert + + * closefrom.c, getcwd.c: dirfd() is now defined in compat.h as + needed. + +2004-06-01 14:30 millert + + * CHANGES: Clarify closefrom() note. + +2004-06-01 12:51 millert + + * parse.c: When checking for a command in the directory, only copy + the base dir once. + +2004-06-01 12:44 millert + + * closefrom.c: If there is a /proc/$$/fd directory, behave like the + Solaris closefrom() and only close the descriptors listed + therein. + +2004-06-01 12:23 millert + + * alloc.c: compat.h guarantees INT_MAX is defined. + +2004-06-01 12:23 millert + + * compat.h: Add definitions of OPEN_MAX and INT_MAX for those + without it and remove definition of RLIM_INFINITY (now unused). + +2004-05-31 21:22 millert + + * CHANGES, alloc.c, check.c, compat.h, find_path.c, getcwd.c, + parse.c, sudo.c, sudo.h, visudo.c: Use PATH_MAX, not MAXPATHLEN + since the former is standardized. + +2004-05-31 19:18 millert + + * CHANGES: sync + +2004-05-31 19:10 millert + + * RUNSON: Add some entries that were mailed in a while ago + +2004-05-31 14:16 millert + + * closefrom.c: o sysconf returns a long, not an int. o check for + negative return value from sysconf/getdtablesize and use + OPEN_MAX in this case. o define OPEN_MAX to 256 for those + without it (a fair guess...) + +2004-05-30 12:25 millert + + * UPGRADE: Mention change in parse order for RunAs entries. + +2004-05-30 12:15 millert + + * configure: regen + +2004-05-29 18:29 millert + + * config.h.in, configure.in, INSTALL, README.LDAP: o --with-ldap + now takes an optional dir as a parameter + o added check for ldap_initialize() and start_tls_s() + +2004-05-29 14:54 millert + + * README.LDAP: Fix some typos, word choice and formatting issues. + +2004-05-28 18:06 millert + + * tgetpass.c: Use SA_INTERRUPT so SunOS works correctly, avoid + stdio and just use read/write as it is simpler. + +2004-05-28 16:27 millert + + * configure, configure.in: Remove hack overriding cross-compiler + check. It should no longer be needed. + +2004-05-28 16:26 millert + + * compat.h: Remove select() compat bits since we no longer use + select(). + +2004-05-28 16:24 millert + + * CHANGES, tgetpass.c: Use alarm() instead of select() for the + timeout for systems that don't fully/properly implement select(). + +2004-05-27 19:14 millert + + * CHANGES: synbc + +2004-05-27 19:12 millert + + * RUNSON: update + +2004-05-27 19:12 millert + + * set_perms.c: Deal with systems that have no way of setting the + effective uid such as nsr-tandem-nsk. + +2004-05-27 19:01 millert + + * configure, configure.in: Define NO_SAVED_IDS if we don't find + seteuid() + +2004-05-27 18:21 millert + + * config.h.in, configure, configure.in: Add back check for + setreuid() since NSK doesn't have it. + +2004-05-27 15:57 millert + + * sudoers.cat, sudoers.man.in: regen + +2004-05-27 15:56 millert + + * BUGS, CHANGES: sync + +2004-05-27 15:55 millert + + * parse.c: In sudoers_lookup() return VALIDATE_NOT_OK if the runas + user was explicitly denied and the command matched. This fixes a + long-standing bug and makes: foo machine = (ALL) + /usr/bin/blah foo machine = (!bar) /usr/bin/blah + + equivalent to: foo machine = (ALL, !bar) /usr/bin/blah + +2004-05-27 15:52 millert + + * sudoers.pod: Clarify mail_noperm + +2004-05-19 21:25 aaron + + * Makefile.in: Missing DESTDIR in make install for sudo_noexec.la + +2004-05-17 18:32 millert + + * sudo.man.in, sudoers.man.in, visudo.man.in, sudo.cat, + sudoers.cat, visudo.cat: regen + +2004-05-17 18:31 millert + + * TODO: sync + +2004-05-17 18:31 millert + + * sample.sudoers, sudoers.pod: Remove fastboot/fasthalt (who still + remembers these?) and add a minimal sudoedit example. + +2004-05-17 18:21 millert + + * CHANGES, INSTALL, TROUBLESHOOTING, UPGRADE, sudo.c, visudo.c: + filesystem -> file system + +2004-05-17 18:19 millert + + * sudo.pod, sudoers.pod: Fix some minor typos and formatting goofs + +2004-05-17 18:10 millert + + * lex.yy.c: regen + +2004-05-17 17:57 millert + + * visudo.pod: remove my email addr + +2004-05-17 17:55 millert + + * sudo.pod, sudoers.pod, visudo.pod: Use @mansectform@ and + @mansectsu@ everywhere Make man page references links with L<> + +2004-05-17 16:51 millert + + * parse.lex: Accept quoted globbing characters and pass them + verbatim for fnmatch() + +2004-05-17 16:50 millert + + * UPGRADE: Document that /tmp/.odus is gone. + +2004-05-17 16:28 millert + + * CHANGES, aclocal.m4, configure, pathnames.h.in: No longer use + /tmp/.odus as a possible timestamp dir unless specifically + configured to do so. Instead, if no /var/run exists, use + /var/adm/sudo or /usr/adm/sudo. + +2004-05-17 16:08 millert + + * check.c, compat.h, logging.c, set_perms.c, sudo.c, tgetpass.c, + visudo.c: Preliminary changes to support nsr-tandem-nsk. Based + on patches from Tom Bates. + +2004-05-16 18:47 millert + + * CHANGES: There was no 1.6.7p6. + +2004-05-16 16:38 millert + + * BUGS, CHANGES: sync + +2004-05-16 16:36 millert + + * Makefile.in: add missing files to DISTFILES + +2004-05-16 16:23 millert + + * sudoers.man.in, sudo.cat, sudoers.cat, visudo.cat: regen + +2004-05-16 16:20 millert + + * Makefile.in: Fix some line wrap and update (c) year + +2004-04-28 15:05 aaron + + * README.LDAP: Build Note + +2004-04-06 22:03 aaron + + * Makefile.in: Fix install-dirs + +2004-04-04 20:27 millert + + * visudo.c: In Exit() when used as a signal handler, emsg is a + pointer so sizeof() is wrong so make it a #define instead. Also + avoid using a negative exit value. Found by Aaron Campbell + +2004-03-24 18:23 millert + + * sudoers.pod: Remove bogus sentence about uids in a User_List. + Document usernames vs. uid parsing in a Runas_List. + +2004-03-24 18:06 millert + + * parse.c, parse.h, parse.yacc, sudo.c, testsudoers.c, visudo.c: If + the user specified a uid with the -u flag and the uid exists in + the passwd file, set runas_user to the name, not the uid. + + When comparing usernames in sudoers, if a name is really a uid + (starts with '#') compare it numerically to pw_uid. + +2004-03-22 13:35 millert + + * auth/kerb5.c: krb5_mcc_ops should be const; Johnny C. Lam + +2004-02-28 18:54 aaron + + * CHANGES, config.h.in, ldap.c: Added start_tls support + +2004-02-14 18:04 millert + + * Makefile.in: Clean up libtool stuff for 'make distclean' and add + def_data.c, def_data.h to PARSESRCS. + +2004-02-14 10:13 aaron + + * strlcat.c, strlcpy.c: Un-Fix last license munge + +2004-02-13 16:37 millert + + * CHANGES, RUNSON, TODO: checkpoint + +2004-02-13 16:37 millert + + * lex.yy.c, configure: regen + +2004-02-13 16:36 millert + + * LICENSE, Makefile.binary, Makefile.in, alloc.c, check.c, + closefrom.c, compat.h, defaults.c, defaults.h, env.c, fileops.c, + find_path.c, getprogname.c, getspwuid.c, goodpath.c, ins_2001.h, + ins_classic.h, ins_csops.h, ins_goons.h, insults.h, interfaces.c, + interfaces.h, ldap.c, logging.c, logging.h, parse.c, parse.h, + parse.lex, parse.yacc, pathnames.h.in, set_perms.c, sigaction.c, + strerror.c, strlcat.c, strlcpy.c, sudo.c, sudo.h, sudo.man.in, + sudo.pod, sudo_edit.c, sudo_noexec.c, sudoers.man.in, + sudoers.pod, testsudoers.c, tgetpass.c, utime.c, version.h, + visudo.c, visudo.man.in, visudo.pod, zero_bytes.c, 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, auth/sudo_auth.h, + emul/search.h, emul/utime.h: More to a less restrictive, + ISC-style license. + +2004-02-12 21:08 aaron + + * CHANGES, Makefile.in, README.LDAP, config.h.in, configure.in, + def_data.c, def_data.h, def_data.in, ldap.c, sudo.c, sudo.h, + sudoers2ldif: Merged in LDAP Support + +2004-02-08 15:53 millert + + * sudo.h, sudo_noexec.c: Only do "extern int errno" if errno is not + a macro. + +2004-02-06 18:08 millert + + * set_perms.c: setreuid(0, 0) fails on QNX if the euid is not + already 0 so set the euid first, then just call setuid(0) to set + the real uid too. + +2004-02-06 14:52 millert + + * set_perms.c: Use setresuid() and setreuid() for PERM_RUNAS when + appropriate instead of seteuid() which may not exist. + +2004-02-04 14:58 millert + + * LICENSE: 2004 + +2004-02-03 23:38 millert + + * INSTALL, config.h.in, configure, configure.in, ins_classic.h: Add + --with-pc-insults configure option + +2004-02-03 23:32 millert + + * visudo.man.in: Prefer VISUAL over EDITOR like old vipw did. + +2004-02-01 15:45 millert + + * sudo.man.in, sudoers.man.in: regen + +2004-02-01 15:44 millert + + * sudoers.pod: Add a note that noexec is not a cure-all. + +2004-02-01 15:20 millert + + * sudoers.pod: Mention that disabling "root_sudo" is pretty + pointless. + +2004-02-01 15:20 millert + + * configure, configure.in: Substitute for root_sudo in sudoers.pod + +2004-02-01 15:03 millert + + * sudo.pod: Add sudoedit to the NAME section + +2004-02-01 15:00 millert + + * sudoers.pod: Document that fact that setting ignore_dot in + sudoers has no effect due to the fact that find_path() is called + *before* sudoers is read. + +2004-01-29 19:50 millert + + * sudo_edit.c: Do not require _PATH_USRTMP to be set. + +2004-01-29 19:42 millert + + * BUGS, CHANGES, TODO: sync + +2004-01-29 19:42 millert + + * sudo.man.in: regen + +2004-01-29 19:41 millert + + * sudo.pod: Clarify that when sudo is run by root with the + SUDO_USER variable set, the sudoers lookup happens for root and + not the SUDO_USER user. + +2004-01-29 17:33 millert + + * defaults.c, env.c, fnmatch.c, interfaces.c, logging.c, parse.c, + set_perms.c, sigaction.c, sudo.c, tgetpass.c, auth/pam.c, + auth/sudo_auth.c: Use the SET, CLR and ISSET macros. + +2004-01-29 16:22 millert + + * interfaces.h: MAIN was replaced with _SUDO_MAIN some time ago. + +2004-01-29 16:15 millert + + * sudo.c: Don't look at prev_user until after we've parsed sudoers + and done the password check. That way, if sudo/sudoedit is run + from a root process that was invoked by sudo, we check sudoers + for root, not the previous user. This makes sudoedit much more + useful and means that for the sudo case, we get correct logging + on who actually ran the command. + +2004-01-22 19:22 millert + + * sudo_edit.c: Add a comment describing why we need to be notified + about our child stopping. + +2004-01-22 16:06 millert + + * def_data.c, def_data.in: Update the noexec variable descriptions + +2004-01-22 14:18 millert + + * sudoers.man.in, sudoers.pod: noexec now replaces more than just + execve() + +2004-01-22 12:14 millert + + * sudo_noexec.c: Alas, all the world does not go through execve(2). + Many systems still have an execv(2) system call, Linux 2.6 + provides fexecve(2) and it is not uncommon for libc to have + underscore ('_') versions of the functions to be used internally + by the library. Instead of stubbing all these out by hand, + define a macro and let it do the work. Extra exec functions + pointed out by Reznic Valery. + +2004-01-21 21:57 millert + + * sudo.c, sudo_edit.c: Fix suspending the editor in -e mode. + Because we do a fork() first we need to be notified when the + child has been stopped and then send that same signal to ourself + so the shell can do its job control thing. + +2004-01-21 21:44 millert + + * visudo.c: Use WIFEXITED and WEXITSTATUS macros. If there are + systems out there that want to run sudo that still don't support + these we can try to deal with that later. + +2004-01-21 20:03 millert + + * lex.yy.c: regen + +2004-01-21 20:00 millert + + * sudo.man.in, sudo.pod, sudoers.man.in, sudoers.pod: Document sudo + -e / sudoedit + +2004-01-21 19:08 millert + + * configure, configure.in: fix typo + +2004-01-21 19:02 millert + + * config.h.in, configure.in: Add SET/CLR/ISSET + +2004-01-21 18:55 millert + + * sudo.c: Allow non-exclusive flags when invoked as sudoedit. + Pretty print the long usage() line to not wrap (assumes 80 char + display) + +2004-01-21 18:01 millert + + * Makefile.in, sudo.c: If sudo is invoked as "sudoedit" the -e flag + is implied and no other flags are permitted. + +2004-01-21 18:00 millert + + * sudo.h: Add a new flag, -e, that makes it possible to give users + the ability to edit files with the editor of their choice as the + invoking user, not the runas user. Temporary files are used for + the actual edit and the temp file is copied over the original + after the editor is done. + +2004-01-21 17:25 millert + + * Makefile.in, parse.c, parse.lex, sudo.c, sudo_edit.c: Add a new + flag, -e, that makes it possible to give users the ability to + edit files with the editor of their choice as the invoking user, + not the runas user. Temporary files are used for the actual edit + and the temp file is copied over the original after the editor is + done. + +2004-01-21 17:06 millert + + * sudo.c, env.c: If real uid == 0 and the SUDO_USER environment + variables is set, use that to determine the invoking user's true + identity. That way the proper info gets logged by someone who + has done "sudo su" but still uses sudo to as root. We can't do + this for non-root users since that would open up a security hole, + though perhaps it would be acceptable to use getlogin(2) on OSes + where this a system call (and doesn't just look in the utmp + file). + +2004-01-21 16:58 millert + + * pathnames.h.in: Add _PATH_TMP, _PATH_VARTMP and _PATH_USRTMP + +2004-01-21 16:57 millert + + * configure, config.h.in, configure.in: Add check for fchown(2) + +2004-01-20 14:22 millert + + * sudo.c: Back out portions of the -i commit that set NewArgv[0] in + set_runaspw. It is far to late to set NewArgv[0] there and will + have no effect anyway as cmnd and safe_cmnd have already been + set. + +2004-01-20 14:18 millert + + * visudo.c, visudo.pod: Prefer VISUAL over EDITOR like old vipw + did. + +2004-01-18 20:17 millert + + * env.c, sudo.c: In -i mode always set new environment based on the + runas user's passwd entry. + +2004-01-18 17:56 millert + + * sudo.man.in, sudo.pod: Document the new -i flag and sync SYNOPSIS + section with usage() in sudo.c. Also sort the flags in the + OPTIONS section. + +2004-01-18 17:55 millert + + * sudo.c, sudo.h: o Add -i that acts similar to "su -", based on + patches from David J. MacKenzie o Sort the flags in the usage + message + +2004-01-18 17:22 millert + + * sudoers.man.in, sudoers.pod: Add a missing @runas_default@ + substitution. + +2004-01-17 16:34 millert + + * sudo.c: Change euid to runas user before calling find_path(). + Unfortunately, though runas_user can be modified in sudoers we + haven't parsed sudoers yet. + +2004-01-17 16:25 millert + + * sudoers.man.in, sudoers.pod: Add missing defintion of + Parameter_List and use single pipes in the Defaults EBNF + definition. + +2004-01-17 13:49 millert + + * sudo.c: Fix a bug when set_runaspw() is used as a callback. We + don't want to reset the contents of runas_pw if the user + specified a user via the -u flag. + + Avoid unnecessary passwd lookups in set_authpw(). In most cases + we already have the info in runas_pw. + +2004-01-16 18:16 millert + + * check.c: Add Stan Lee / Uncle Ben quote to the lecture from + RedHat + +2004-01-16 18:12 millert + + * sudo.h: Update sudo_getepw() proto and add one for set_runaspw() + +2004-01-16 18:10 millert + + * parse.c: If we can't stat the command as root, try as the runas + user instead. + +2004-01-16 18:09 millert + + * testsudoers.c, visudo.c: Add stub set_runaspw() function + +2004-01-16 18:09 millert + + * sudo.c: Add set_runaspw() function to fill in runas_pw. This + will be used as a callback to update runas_pw when the runas user + changes. + +2004-01-16 18:07 millert + + * env.c, sudo.c: PERM_RUNAS -> PERM_FULL_RUNAS + +2004-01-16 18:05 millert + + * set_perms.c, sudo.h: Rename PERM_RUNAS -> PERM_FULL_RUNAS and add + a PERM_RUNAS that just changes the euid. + +2004-01-16 18:04 millert + + * getspwuid.c: Make sudo_pwdup() act like OpenBSD pw_dup() and + allocate memory in one chunk for easy free()ing. Also change it + from static to extern. + +2004-01-16 18:03 millert + + * defaults.c, defaults.h: Add callback support + +2004-01-16 18:02 millert + + * def_data.c, def_data.in, mkdefaults: Add a callback field and use + it for runas_default + +2004-01-15 15:13 millert + + * auth/fwtk.c: Add support for chalnecho and display server + responses used by fwtk >= 2.0 + +2004-01-12 18:39 millert + + * sudoers.man.in, sudoers.pod: ld.so is ld.so.1 on solaris + +2004-01-12 14:03 millert + + * Makefile.in, config.h.in, configure, configure.in, sudo.c, + sudo.h: Use closefrom() instead of doing the equivalent inline. + +2004-01-12 13:55 millert + + * closefrom.c: closefrom(3) for systems w/o it + +2004-01-09 16:29 millert + + * sudoers.man.in: Update from .pod file. + +2004-01-09 16:26 millert + + * configure, configure.in: Substitute noexec_file for the sudoers + man page + +2004-01-09 16:24 millert + + * sudo.man.in, sudo.pod: Mention noexec + +2004-01-09 16:16 millert + + * sudoers.man.in, sudoers.pod: Document noexec + +2004-01-09 14:38 millert + + * config.h.in, configure.in, auth/pam.c: Move PAM_CONST macro + definition from config.h to pam.c where it belongs. We can't + have this in config.h since that gets included too early. + +2004-01-09 14:35 millert + + * config.h.in, configure, configure.in, auth/pam.c: Some PAM + implementations put their headers in /usr/include/pam instead of + /usr/include/security. + +2004-01-09 14:32 millert + + * configure.in: I missed changing the EXEC macro -> EXECV here when + I changed this in config.h.in and sudo.c a while ago. + +2004-01-09 13:15 millert + + * acsite.m4: OpenBSD vax/m88k/hppa don't do shared libs + +2004-01-09 03:29 millert + + * configure, configure.in: o merge the hpux case entries into a + single entry w/ its own sub-case statement. o HP-UX >= 11 + support getspnam(), use it in preference to getprpwuid() + +2004-01-09 02:58 millert + + * configure, configure.in: eval $shrext so that it expands nicely + on MacOS X + +2004-01-09 02:50 millert + + * Makefile.in: Don't lie about making a module, it does the wrong + thing on mach + +2004-01-09 02:49 millert + + * ltmain.sh: Remove requirement that libs must begin with "lib". + They don't when we point directly at the lib using LD_PRELOAD or + its equivalent. + +2004-01-09 02:01 millert + + * acsite.m4: Disable support for c++, f77 and java. We don't need + it, it takes a lot of time, and it hosed our check for shared lib + support. + +2004-01-09 02:00 millert + + * configure: regen + +2004-01-09 02:00 millert + + * configure.in: Call AC_ENABLE_SHARED and check the status of + enable_shared to know when shared libs are available. + +2004-01-09 01:37 millert + + * acsite.m4: Duh, OpenBSD suports shared libs too + +2004-01-09 01:18 millert + + * configure.in, config.h.in: Only OpenPAM and Linux PAM use const + qualifiers. + +2004-01-09 01:15 millert + + * configure, configure.in: o No need to check for sed, libtool + config does that for us o move check for --with-noexec until + after libtool magic is run so we can use $can_build_shared and + $shrext + +2004-01-09 01:14 millert + + * ltmain.sh: Don't print a bunch of crap about library installs + since we are not really installing a library. + +2004-01-09 00:38 millert + + * env.c: Make format_env() varargs Add noexec support for Darwin, + MacOS X, Irix, and Tru64 + +2004-01-09 00:32 millert + + * acsite.m4, ltconfig, ltmain.sh: Update to libtool 1.5 with local + changes: o no ldconfig in the finish step o assume no libprefix + or version is needed + +2004-01-09 00:15 millert + + * sudo_noexec.c: Fix compilation under K&R + +2004-01-06 09:31 millert + + * CHANGES: checkpoint + +2004-01-06 09:28 millert + + * sudo_noexec.c: stub execve() that just returns EACCES; used for + noexec functionality + +2004-01-06 01:42 millert + + * sudo.tab.h: Regen w/ updated byacc from OpenBSD; fixes a gcc 3.2 + issue with generated code. + +2004-01-05 16:10 millert + + * def_data.c, def_data.h, def_data.in: Move the environment + defaults to the end and shorten a few of the descriptions. + +2004-01-05 15:05 millert + + * configure.in, configure: no shared libs on ultris or convexos + +2004-01-05 15:03 millert + + * Makefile.in, configure, configure.in: Build sudo_noexec shared + object using libtool; could use some cleanup. + +2004-01-05 14:59 millert + + * acsite.m4, ltconfig, ltmain.sh: libtool scaffolding + +2004-01-05 14:56 millert + + * parse.yacc: Merge the NOPASSWD/PASSWD and NOEXEC/EXEC rules so + that order is not important. + +2004-01-05 12:15 millert + + * defaults.c, env.c, parse.c, parse.h, parse.lex, parse.yacc, + pathnames.h.in, sudo.c, sudo.h, lex.yy.c: update copyright year + +2004-01-04 22:58 millert + + * configure, configure.in, defaults.c, env.c, pathnames.h.in: Add + _PATH_SUDO_NOEXEC and corresponding --with-noexec configure + option. The default value of noexec_file is set to this. + +2004-01-04 21:48 millert + + * def_data.c, def_data.h, def_data.in, env.c, lex.yy.c, parse.c, + parse.h, parse.lex, parse.yacc, sudo.c, sudo.h, sudo.tab.h: Add + support for preloading a shared object containing a dummy + execve() function that just sets error and returns -1. This adds + a "noexec_file" option to load the filename as well as a "noexec" + flag to enable it unconditionally. There is also a NOEXEC tag + that can be attached to specific commands and an EXEC tag to + disable it. + +2004-01-04 21:40 millert + + * mkdefaults: add missing newline to usage statement + +2004-01-04 20:39 millert + + * config.h.in, sudo.c: Rename EXEC macro -> EXECV + +2004-01-04 20:16 millert + + * logging.c: Don't truncate usernames to 8 characters in the log + message. + +2004-01-04 20:13 millert + + * check.c, sudoers.man.in, sudoers.pod: Update copyright year + +2004-01-04 20:12 millert + + * check.c, def_data.c, def_data.h, def_data.in, sudoers.man.in, + sudoers.pod: Add a new option, lecture_file, that can be used to + point to a custom sudo lecture. + +2003-12-31 17:46 millert + + * Makefile.in, sudo.h, zero_bytes.c, auth/aix_auth.c, + auth/bsdauth.c, auth/fwtk.c, auth/pam.c, auth/sudo_auth.c: Add a + zero_bytes() function to do the equivalent of bzero in such a way + that will heopfully not be optimized away by sneaky compilers. + +2003-12-31 13:35 millert + + * err.c: Use #ifdef __STDC__, not #if __STDC__. + +2003-12-30 17:41 millert + + * mkdefaults: Always put at least one space between the def_* macro + name and its definition. + +2003-12-30 17:34 millert + + * configure, configure.in: Adjust code for --without-lecture to + match new values. + +2003-12-30 17:33 millert + + * visudo.man.in: regen after pasto fix + +2003-12-30 17:31 millert + + * sudoers.man.in, sudoers.pod: Document that "lecture" has changed + from a flag to a tuple. + +2003-12-30 17:31 millert + + * check.c, def_data.c, def_data.h, def_data.in, defaults.c, + defaults.h, logging.c, mkdefaults, parse.c, sudo.c, sudo.h: Add + support for tuples in def_data.in; these are implemented as an + enum type. Currently there is only a single tuple enum but in + the future we may have one tuple enum per T_TUPLE entry in + def_data.in. Currently listpw, verifypw and lecture are tuples. + This avoids the need to have two entries (one ival, one str) for + pwflags and syslog values. + + lecture is now a tuple with the following values: never, once, + always + + We no longer use both an int and string entry for syslog + facilities and priorities. Instead, there are logfac2str() and + logpri2str() functions that get used when we need to print the + string values. + +2003-12-30 17:20 millert + + * check.c, def_data.h, defaults.c, defaults.h, env.c, find_path.c, + logging.c, mkdefaults, parse.c, parse.yacc, set_perms.c, sudo.c, + visudo.c, auth/aix_auth.c, auth/bsdauth.c, auth/fwtk.c, + auth/pam.c, auth/rfc1938.c, auth/securid5.c, auth/sia.c, + auth/sudo_auth.c: Create def_* macros for each defaults value so + we no longer need the def_{flag,ival,str,list,mode} macros (which + have been removed). This is a step toward more flexible data + types in def_data.in. + +2003-12-30 15:55 millert + + * TODO: checkpoint + +2003-12-22 21:18 millert + + * sudo.c: If we are in -k/-K mode, just spew to stderr. It is not + unusual for 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. Previously, this would result in useless mail + and logging. + +2003-12-16 13:51 millert + + * visudo.pod: fix pasto in VISUAL description + +2003-12-09 22:09 millert + + * configure: regen + +2003-12-09 22:08 millert + + * CHANGES: checkpoint + +2003-12-09 22:02 millert + + * TROUBLESHOOTING: Some OSes (like Solaris) allow export w/ nosuid + too + +2003-08-12 16:45 millert + + * compat.h: We don't use FD_ZERO anymore so just define FD_SET (if + not already there). + +2003-06-28 21:31 millert + + * auth/pam.c: Fix a core dump on Solaris by preserving the + pam_handle_t we used during authentication for pam_prep_user(). + If we didn't authenticate (ie: ticket still valid), we call + pam_init() from pam_prep_user(). This is something of a hack; it + may be better to change the auth API and add an auth_final() + function that acts like pam_prep_user(). + +2003-06-21 12:50 millert + + * set_perms.c: Add explicit declaration of printerr variable in + function header (was defaulting to int which is OK but oh so K&R + :-). From Theo. + +2003-06-09 19:00 millert + + * config.h.in, configure.in: s/HAVE_STOW/USE_STOW/ + +2003-06-09 16:07 millert + + * logging.c: Also exit waitpid() loop when pid == 0. Fixes a + problem where the sudo process would spin eating up CPU until + sendmail finished when it has to send mail. + +2003-05-30 16:22 millert + + * fnmatch.3, fnmatch.c: Remove advertising clause, UCB has + disavowed it + +2003-05-21 21:53 millert + + * parse.c: Don't assume that getgrnam() calls don't modify contents + of struct passwd returned by getpwnam(). On FreeBSD w/ NIS this + can happen. Based on a patch from Kirk Webb. + +2003-05-06 11:25 millert + + * configure.in: missing ;; + +2003-05-06 00:53 millert + + * configure.in: darwin has a broken setreuid() in at least some + versions + +2003-05-06 00:31 millert + + * env.c: Fix an off by one error when reallocating the environment; + Kevin Pye + +2003-04-30 14:04 millert + + * sudoers.pod: Fix User_Spec definition; SEKINE Tatsuo + +2003-04-28 19:30 millert + + * HISTORY: More info on the early days from Coggs. + +2003-04-21 14:47 millert + + * auth/kerb5.c: remove errant semicolon that prevented compilation + under heimdal + +2003-04-15 20:42 millert + + * Makefile.in, alloc.c, check.c, compat.h, defaults.c, defaults.h, + env.c, fileops.c, find_path.c, getprogname.c, getspwuid.c, + goodpath.c, interfaces.c, interfaces.h, logging.c, parse.c, + parse.lex, parse.yacc, pathnames.h.in, set_perms.c, sigaction.c, + strerror.c, sudo.c, sudo.h, sudo.man.in, sudo.pod, + sudoers.man.in, sudoers.pod, testsudoers.c, tgetpass.c, utime.c, + version.h, visudo.c, visudo.man.in, visudo.pod, 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: add DARPA credit + on affected files + +2003-04-15 20:25 millert + + * LICENSE: slightly different wording for the darpa credit + +2003-04-15 14:37 millert + + * LICENSE: Add DARPA credit + +2003-04-14 16:49 millert + + * auth/kerb5.c: Use krb5_princ_component() instead of + krb5_princ_realm() for MIT Kerberos like we did before I messed + things up ;-) + + Use krb5_principal_get_comp_string() to do the same thing w/ + Heimdal. I'm not sure if the component should be 0 or 1 in this + case. + + #define ENCTYPE_DES_CBC_MD5 ETYPE_DES_CBC_MD5 for Heimdal since + older versions lack ENCTYPE_DES_CBC_MD5. This is gross and there + should be a configure check for this I guess. + +2003-04-13 15:48 millert + + * TROUBLESHOOTING, config.h.in, configure, configure.in, + sample.sudoers: builtin -> built-in; Jason McIntyre + +2003-04-13 15:45 millert + + * sudoers.pod: built in -> built-in; Jason McIntyre + +2003-04-09 16:14 millert + + * CHANGES: checkpoint for 1.6.7p3 + +2003-04-09 16:14 millert + + * HISTORY: Update info on the early years @ SUNY-Buffalo from Cliff + Spencer. Amazingly, sudo source from 1985 is available via + groups.google.com + +2003-04-09 16:13 millert + + * sudo.c: Don't change rl.rlim_max for RLIMIT_CORE. We need only + set rl.rlim_cur to 0 to turn off core dumps. This may be needed + for the RLIMIT_CORE restoration on some OSes. + +2003-04-04 12:46 millert + + * auth/kerb5.c: Make this compile on Heimdal and MIT Kerberos 5 + +2003-04-04 12:45 millert + + * config.h.in, configure, configure.in: Check for heimdal even if + we found krb5-config and define HAVE_HEIMDAL. + +2003-04-03 22:04 millert + + * auth/kerb5.c: Replace ETYPE_DES_CBC_MD5 with ENCTYPE_DES_CBC_MD5. + The former is no longer defined by MIT kerb5 (though it used to + be and indeed remains so in Heimdal). + +2003-04-03 10:16 millert + + * mkinstalldirs: Remove newer stuff that passes multiple (possibly + duplicate) directories to "mkdir -p" since that seems to break on + Tru64 Unix at least. This basically brings back what shipped + with sudo 1.6.6. + +2003-04-02 13:57 millert + + * auth/kerb5.c: Correct number of args to + krb5_principal_get_realm() and fix an unclosed comment that hid + the bug. + +2003-04-02 13:45 millert + + * configure: regen + +2003-04-02 13:45 millert + + * BUGS, CHANGES, INSTALL, INSTALL.binary, Makefile.in, README, + configure.in, version.h: ++version + +2003-04-02 13:44 millert + + * configure.in: use krb5-config to determine Kerberos V details if + it exists + +2003-04-02 13:25 millert + + * alloc.c, check.c, compat.h, defaults.c, env.c, find_path.c, + interfaces.c, logging.c, parse.c, sudo.c, sudo.h, testsudoers.c, + visudo.c, auth/fwtk.c, auth/rfc1938.c, auth/securid.c, + auth/securid5.c, auth/sia.c: Use warn/err and getprogname() + throughout. The main exception is openlog(). Since the admin + may be filtering logs based on the program name in the log files, + hard code this to "sudo". + +2003-04-02 13:16 millert + + * Makefile.in: Add getprogname.c and err.c + +2003-04-02 13:15 millert + + * configure: regen + +2003-04-02 13:15 millert + + * configure.in, config.h.in: Add checks for getprognam(), + __progname and err.h + +2003-04-02 13:14 millert + + * err.c, emul/err.h: For systems withour err/warn functions. + +2003-04-02 13:14 millert + + * getprogname.c: For systems neither getprogname() nor __progname; + uses Argv[0]. + +2003-04-01 10:09 millert + + * CHANGES: checkpoint for 1.6.7p1 + +2003-04-01 10:02 millert + + * sudo.c, testsudoers.c: fix strlcpy() rval check (innocuous) + +2003-04-01 09:58 millert + + * check.c: oflow detection in expand_prompt() was faulty (false + positives). The count was based on strlcat() return value which + includes the length of the entire string. + +2003-03-30 19:02 millert + + * CHANGES, RUNSON, TODO: checkpoint for the sudo 1.6.7 release + +2003-03-24 16:09 millert + + * logging.c: g/c unused variable + +2003-03-24 11:06 millert + + * configure: regen + +2003-03-24 11:05 millert + + * configure.in: use man sections 8 and 5 for csops + +2003-03-21 18:11 millert + + * configure: regen + +2003-03-21 15:10 millert + + * configure.in: Add -lskey or -lopie directly to SUDO_LIBS instead + of having AC_CHECK_LIB() add them to LIBS. Fixes visudo linkage. + +2003-03-21 14:02 millert + + * configure: regen + +2003-03-21 14:01 millert + + * INSTALL, aclocal.m4, configure.in: Add --with-blibpath for AIX. + An alternate libpath may be specified or -blibpath support can be + disabled. Also change conifgure such that -blibpath is not + specified if no -L libpaths were added to SUDO_LDFLAGS. + +2003-03-20 22:05 millert + + * configure.in: add AIX blibpath support + +2003-03-20 20:28 millert + + * INSTALL, configure.in: --with-skey and --with-opie now take an + option directory argument This obsoletes a --with-csops hack + (/tools/cs/skey) + + Also remove the remaining direct uses of "echo" + +2003-03-20 17:44 millert + + * configure.in: Detect KTH Kerberos IV and deal with it. Also make + -lroken optional for KTH Kerberos IV and V. + +2003-03-20 14:42 millert + + * aclocal.m4: Add SUDO_APPEND_LIBPATH function that add + -L/path/to/dir (and -R/path/to/dir if $with_rpath) to the + specified variable. + +2003-03-20 14:40 millert + + * INSTALL, configure.in: Add -R/path/to/libs for Solaris and SVR4. + There is a new configure option, --with-rpath to control this + behavior. + +2003-03-19 23:50 millert + + * configure.in: for kerb4 put libdes after libkrb on the link line + +2003-03-19 23:49 millert + + * auth/kerb4.c: typo + +2003-03-19 23:33 millert + + * configure.in: fix kerberos lib check when a path is specified + +2003-03-19 21:04 millert + + * logging.c: Fix boolean thinko in SIGCHLD reaper and call + reapchild after sending mail instead of doing a conditional + sudo_waitpid. + +2003-03-19 16:20 millert + + * configure: regen + +2003-03-19 16:19 millert + + * configure.in: replace =DIR with [=DIR] where sensible + +2003-03-19 16:16 millert + + * configure.in: o Use AC_MSG_* instead of "echo" o New Kerberos + include/lib detection based on openssh's configure.in + +2003-03-19 15:58 millert + + * INSTALL: --with-kerb4 and --with-kerb5 now take an optional + argument. + +2003-03-15 22:03 millert + + * auth/securid.c: Kill remaining strcpy(), the programmer's guide + says username is 32 bytes. + +2003-03-15 21:18 millert + + * auth/kerb4.c: trat uid_t as unsigned long for printf and use + snprintf, not sprintf + +2003-03-15 21:18 millert + + * auth/rfc1938.c: use snprintf + +2003-03-15 15:37 millert + + * auth/: afs.c, aix_auth.c, bsdauth.c, dce.c, fwtk.c, kerb4.c, + kerb5.c, pam.c, passwd.c, rfc1938.c, sudo_auth.c: update + copyright year + +2003-03-15 15:31 millert + + * LICENSE, alloc.c, check.c, configure.in, env.c, sudo.c, + Makefile.in, aclocal.m4, compat.h, find_path.c, interfaces.c, + logging.c, parse.c, parse.lex, parse.yacc, set_perms.c, sudo.h, + sudo.pod, sudoers.pod, testsudoers.c, version.h, visudo.c, + visudo.pod, sudo.man.in, sudoers.man.in, visudo.man.in: update + copyright year + +2003-03-15 15:19 millert + + * check.c, env.c, sudo.c: Cast [ug]ids to unsigned long and printf + with %lu + +2003-03-15 15:17 millert + + * configure: regen + +2003-03-15 15:16 millert + + * configure.in: correct error messages for + --with-sudoers-{mode,uid,gid} + +2003-03-15 15:10 millert + + * alloc.c: make the malloc(0) error specific to each function to + aid tracking down bugs. + +2003-03-15 14:49 millert + + * alloc.c: deal with platforms where size_t is signed and there is + no SIZE_MAX or SIZE_T_MAX + +2003-03-15 14:10 millert + + * auth/kerb5.c: Make this compile w/ Heimdal and fix some gcc + warnings. + +2003-03-15 13:02 millert + + * sudo.c: Use stat_sudoers macro so --with-stow can work + +2003-03-15 13:01 millert + + * INSTALL, config.h.in, configure, configure.in: Add support for + --with-stow based on patches from Robert Uhl + +2003-03-15 12:51 millert + + * env.c: fix indentation + +2003-03-15 00:21 millert + + * configure.in: back out rev 1.352 + +2003-03-14 20:11 millert + + * lex.yy.c: regen + +2003-03-14 20:11 millert + + * parse.lex: use strlcpy, not strncpy + +2003-03-14 19:48 millert + + * set_perms.c: Fix typo; check pw_uid, not pw_gid after + setusercontext() failure. + +2003-03-14 19:43 millert + + * logging.c: use pid_t + +2003-03-14 10:43 millert + + * strlcat.c, strlcpy.c: Make gcc shutup about unused rcsid + +2003-03-14 10:35 millert + + * interfaces.c: Move the n == 0 check for the non-getifaddrs cas + +2003-03-13 21:47 millert + + * auth/rfc1938.c: skeychallenge() on NetBSD take a size parameter + +2003-03-13 21:38 millert + + * configure: regen + +2003-03-13 21:38 millert + + * configure.in: put -ldl after -lpam, not before; fixes static + linking on Linux + +2003-03-13 21:17 millert + + * interfaces.c: Avoid malloc(0) and fix the loop invariant for the + getifaddrs() case. + +2003-03-13 20:24 millert + + * sudo.man.in, sudoers.man.in, visudo.man.in, sudo.cat, + sudoers.cat, visudo.cat: regen + +2003-03-13 20:23 millert + + * Makefile.in: Preserve copyright notice from .pod file in .man.in + file + +2003-03-13 20:01 millert + + * visudo.pod: Add sudoers(5) to SEE ALSO + +2003-03-13 15:27 millert + + * lex.yy.c: regen + +2003-03-13 15:27 millert + + * parse.lex: Don't assume libc can realloc() a NULL string. If + malloc/realloc fails, make sure we just return; yyerror() is not + terminal. + +2003-03-13 15:17 millert + + * lex.yy.c: regen + +2003-03-13 15:17 millert + + * parse.lex: simplify fill_args a little and use strlcpy for + paranoia + +2003-03-13 15:00 millert + + * check.c, env.c, find_path.c, parse.c, parse.yacc, sudo.c, + testsudoers.c: Use strlc{at,py} for paranoia's sake and exit on + overflow. In all cases the strings were either pre-allocated to + the correct size of length checks were done before the copy but a + little paranoia can go a long way. + +2003-03-13 12:54 millert + + * sudo.h: Add strlc{at,py} protos + +2003-03-13 12:03 millert + + * env.c, interfaces.c: Use erealloc3() + +2003-03-13 12:00 millert + + * configure: regen + +2003-03-13 12:00 millert + + * alloc.c: Oflow test of nmemb > SIZE_MAX / size is fine (don't + need >=). Use memcpy() instead of strcpy() in estrdup() so this + is strcpy()-free. + +2003-03-13 11:58 millert + + * sudo.c: snprintf() a uid as %lu, not %ld to match the + MAX_UID_T_LEN test in configure. + +2003-03-13 11:56 millert + + * aclocal.m4: In MAX_UID_T_LEN test cast uid_t to unsigned long, + just unsigned. + +2003-03-12 18:46 millert + + * sudo.c: Use snprintf() for paranoia + +2003-03-12 17:16 millert + + * parse.yacc: Use emalloc2 and erealloc3 + +2003-03-12 17:08 millert + + * Makefile.in: strlc{at,py} for those w/o it + +2003-03-12 17:07 millert + + * strlcat.c, strlcpy.c: stlc{at,py} for those w/o it. + +2003-03-12 17:07 millert + + * config.h.in, configure, configure.in: Add stlc{at,py} for those + w/o it. + +2003-03-12 16:51 millert + + * alloc.c, sudo.h: Add erealloc3(), a realloc() version of + emalloc2(). + +2003-03-12 16:45 millert + + * interfaces.c, sudo.c: Use emalloc2() to allocate N things of a + certain size. + +2003-03-12 16:41 millert + + * alloc.c, sudo.h: Add emalloc2() -- like calloc() but w/o the + bzero and with error/oflow checking. + +2003-03-12 16:23 millert + + * alloc.c: Error out on malloc(0); suggested by theo + +2003-03-09 19:34 millert + + * configure, configure.in: fix a typo; David Krause + +2003-03-07 10:46 millert + + * sudo.pod: fix typo + +2003-03-03 21:47 millert + + * env.c: Remove DYLD_ from the environment for MacOS X; from bbraun + +2003-03-01 13:20 millert + + * configure.in, config.h.in: not not; Anil Madhavapeddy + +2003-01-23 03:03 millert + + * sudo.pod, sudoers.pod, visudo.pod: typos; jmc@openbsd.org + +2003-01-20 16:13 millert + + * parse.yacc: Add some missing ';' rule terminators that bison + warns about. + +2003-01-20 16:07 millert + + * config.sub: fix typo I introduced in last merge + +2003-01-20 15:59 millert + + * configure: regenerate with autoconf 2.57 + +2003-01-20 15:58 millert + + * config.h.in: Add missing "$HOME" + +2003-01-20 15:57 millert + + * configure.in: Add some more square backets to make autoconf 2.57 + happy + +2003-01-20 14:39 millert + + * config.guess, config.sub, mkinstalldirs: Updates from + autoconf-2.57 + +2003-01-17 18:10 millert + + * lex.yy.c, sudo.tab.h: regen + +2003-01-17 18:09 millert + + * parse.lex, parse.yacc, sudoers.pod: Add support for + Defaults>RunasUser + +2003-01-06 19:10 millert + + * visudo.c: fclose() yyin after each yyparse() is done and use + fopen() instead of using freopen(). + +2003-01-06 19:02 millert + + * parse.lex: Better fix for sudoers files w/o a newline before EOF. + It looks like the issue is that yyrestart() does not reset the + start condition to INITIAL which is an issue since we parse + sudoers multiple times. + +2003-01-06 18:47 millert + + * parse.lex: Work around what appears to be a flex bug when dealing + with files that lack a final newline before EOF. This adds a + rule to match EOF in the non-initial states which resets the + state to INITIAL and throws an error. + +2003-01-06 15:06 millert + + * visudo.c: o The parser needs sudoers to end with a newline but + some editors (emacs) may not add one. Check for a missing + newline at EOF and add one if needed. o Set quiet flag during + initial sudoers parse (to get options) o Move yyrestart() call + and always use freopen() to open yyin after initial sudoers + parse. + +2002-12-15 11:24 millert + + * set_perms.c: Fix pasto/thinko in setresgid()/setregid() usage. + Want to set effective gid, not real gid, when reading sudoers. + +2002-12-15 11:08 millert + + * set_perms.c: don't compile set_perms_posix if we have setreuid or + setresuid + +2002-12-14 14:21 millert + + * sudo.pod, sudoers.pod: document new prompt escapes + +2002-12-14 14:15 millert + + * check.c: Add %U and %H escapes and redo prompt rewriting. "%%" + now gets collapsed to "%" as was originally intended. This also + gets rid of lastchar (does lookahead instead of lookback) which + should simplify the logic slightly. + +2002-12-13 13:20 millert + + * tgetpass.c: Write the prompt *after* turning off echo to avoid + some password characters being echoed on heavily-loaded machines + with fast typists. + +2002-12-13 13:09 millert + + * config.sub: Add support for mipseb; wiz@danbala.tuwien.ac.at + +2002-12-13 12:48 millert + + * configure.in: Fix IRIX fallout from name changes in man dir/sect + Makefile variables. Patch from erici AT motown DOT cc DOT utexas + DOT edu + +2002-12-13 11:33 millert + + * auth/pam.c: Keep a local copy of tgetpass_flags so we don't add + in TGP_ECHO to the global copy. Problem noted by Peter Pentchev. + +2002-11-28 18:43 millert + + * parse.yacc: Add missing yyerror() calls; YYERROR does not seem to + call this for us. + +2002-11-26 12:09 millert + + * sudo.c: fix typo in comment; Pedro Bastos + +2002-11-22 14:41 millert + + * INSTALL: document --disable-setresuid + +2002-11-22 14:41 millert + + * auth/: aix_auth.c, bsdauth.c, fwtk.c, pam.c, sudo_auth.c: + Sprinkle some volatile qualifiers to prevent over-enthusiastic + optimizers from removing memset() calls. + +2002-11-22 14:11 millert + + * logging.c, parse.yacc: minor sign fixes pointed out by gcc + -Wsign-compare + +2002-11-22 14:09 millert + + * set_perms.c, sudo.c, sudo.h: Revamp set_perms. We now use a + version based on setresuid() or setreuid() when possible since + that allows us to support the stay_setuid option and we always + know exactly what the semantics will be (various Linux kernels + have broken POSIX saved uid support). + +2002-11-22 14:08 millert + + * config.h.in, configure: regen from configure.in + +2002-11-22 14:07 millert + + * configure.in: Add checks for setresuid() and a way to disable + using it + +2002-11-22 14:05 millert + + * compat.h: No long need to emulate set*[ug]id() via setres[ug]id() + or setre[ug]id(). The new set_perms stuff only uses things it + knows are there. + +2002-11-22 13:33 millert + + * sudo.c: Before exec, restore state of signal handlers to be the + same as when we were initialy invoked instead of just reseting to + SIG_DFL. Fixes a problem when using sudo with nohup. Based on a + patch from Paul Markham. + +2002-11-22 13:23 millert + + * sudo.c: o timestamp_uid should be uid_t, not int o clarify error + message when sudo is run by root and no_root_sudo is set + +2002-09-19 17:27 millert + + * README: update ftp link for bison + +2002-07-20 08:30 millert + + * set_perms.c: Error out if setusercontext() fails and the runas + user is not root. + +2002-05-20 16:51 millert + + * auth/securid5.c: Fix rcsid + +2002-05-20 16:50 millert + + * configure.in: Fix SecurID API test + +2002-05-17 13:20 millert + + * env.c: typo in comment + +2002-05-17 13:20 millert + + * configure.in: securid5 stuff needs pthreads. Just adding + -lpthread is suboptimal but I don't see a better way at the + moment. + +2002-05-17 13:04 millert + + * Makefile.in, auth/securid5.c: SecurID API version 5 support from + Michael Stroucken + +2002-05-17 13:02 millert + + * configure.in: Add check for SecurID 5.0 API + +2002-05-08 16:46 millert + + * strerror.c: We actually do still need config.h to get the 'const' + definition for K&R C. + +2002-05-05 16:43 millert + + * configure: regen with autoconf 2.5.3 + +2002-05-05 16:25 millert + + * configure.in: Don't set sysconfdir to '/etc' if the user has + specified a --prefix. + +2002-05-05 16:14 millert + + * configure.in: Some fixes for autoconf 2.53 from Robert Uhl o + don't AC_SUBST LIBOBJS o force a 4th arg for AC_CHECK_HEADER() + to workaround a bug + +2002-05-05 15:58 millert + + * env.c, sudo.c, sudo.h: No need for dump_badenv() now that + dump_defaults() knows how to dump lists. + +2002-05-04 21:31 millert + + * BUGS, INSTALL, Makefile.in, configure.in, version.h, + INSTALL.binary, README: ++version + +2002-05-04 20:57 millert + + * sudoers.pod: document timestampowner + +2002-05-04 20:45 millert + + * check.c: Don't call set_perms() when doing timestamp stuff unless + timestamp_uid != 0. + +2002-05-04 20:43 millert + + * check.c, logging.c, parse.c, set_perms.c, sudo.c, sudo.h, + testsudoers.c, auth/sudo_auth.c: g/c second arg to set_perms--it + is no longer used + +2002-05-03 18:48 millert + + * check.c, set_perms.c, sudo.c, sudo.h: Add support for non-root + timestamp dirs. This allows the timestamp dir to be shared via + NFS (though this is not recommended). + +2002-05-03 18:47 millert + + * def_data.c, def_data.h, def_data.in: Add timestampowner, "Owner + of the authentication timestamp dir" + +2002-05-02 15:40 millert + + * env.c: Don't try to pre-compute the size of the new envp, just + allocate space up front and realloc as needed. Changes to the + new env pointer must all be made through insert_env() which now + keeps track of spaced used and allocates as needed. + +2002-04-26 15:12 millert + + * configure: regen + +2002-04-26 15:12 millert + + * configure.in: Fix two typo/pastos; from jrj@purdue.edu + +2002-04-25 11:36 millert + + * INSTALL.binary, README: ++version + +2002-04-25 11:35 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat, + visudo.man.in, configure: regen + +2002-04-25 11:31 millert + + * CHANGES, RUNSON, TODO: Sync with 1.6.6 + +2002-04-25 11:30 millert + + * check.c: The the loop used to expand %h and %u, the lastchar + variable was not being initialized. This means that if the last + char in the prompt is '%' and the first char is 'h' or 'u' a + extra copy of the host or user name would be copied, for which + space had not been allocated. + +2002-04-18 11:41 millert + + * BUGS, INSTALL, Makefile.in, configure.in, version.h: crank + version to 1.6.6 + +2002-04-18 11:39 millert + + * auth/afs.c: #undef VOID to get rid of an AFS warning + +2002-04-18 11:38 millert + + * env.c: Use easprintf instead of emalloc + sprintf for some + things. + +2002-03-15 19:45 millert + + * lex.yy.c: regen + +2002-03-15 19:44 millert + + * parse.c, parse.lex, parse.yacc, testsudoers.c: Remove Chris + Jepeway's email address so people don't bug him ;-) + +2002-03-11 22:19 millert + + * sudo.c: Move endpwent() to be after set_perms(PERM_RUNAS, ...) + and also call endgrent() at the same time. + +2002-02-21 22:23 millert + + * INSTALL: Make it clear which configure options take arguments. + +2002-01-25 13:38 millert + + * compat.h: HP-UX 9.x has RLIMIT_* but no RLIM_INFINITY. If there + is no RLIM_INFINITY, just pretend it is -1. This works because + we only check for RLIM_INFINITY and do not set anything to that + value. + +2002-01-22 11:43 millert + + * auth/pam.c: Zero and free allocated memory when there is a + conversation error. + +2002-01-21 22:37 millert + + * auth/bsdauth.c: Use sigaction() not signal() + +2002-01-21 22:26 millert + + * INSTALL: Mention that some linux kernels have broken POSIX saved + ID support + +2002-01-21 21:03 millert + + * CHANGES: checkpoint for 1.6.5p2 + +2002-01-21 21:01 millert + + * configure: regen + +2002-01-21 21:01 millert + + * configure.in: Add --disable-setreuid flag + +2002-01-21 21:00 millert + + * INSTALL: Document new --disable-setreuid option and change + description for --disable-saved-ids to match new error message. + +2002-01-21 21:00 millert + + * set_perms.c: fatal() now takes an argument that determines + whether or not to call perror(). + +2002-01-21 20:58 millert + + * PORTING, TROUBLESHOOTING: Update for new error messages from + set_perms() + +2002-01-21 17:46 millert + + * auth/pam.c: Make this compile w/o warnings + +2002-01-21 17:36 millert + + * auth/pam.c: Mention that we can't use pam_acct_mgmt() + +2002-01-21 17:25 millert + + * auth/: aix_auth.c, bsdauth.c, fwtk.c, pam.c: The user's password + was not zeroed after use when AIX authentication, BSD + authentication, FWTK or PAM was in use. + +2002-01-20 14:21 millert + + * auth/pam.c: Avoid giving PAM a NULL password response, use the + empty string instead. This avoids a log warning when the user + hits ^C at the password prompt when PAM is in use. + +2002-01-19 19:46 millert + + * auth/pam.c: Don't check the return value of pam_setcred(). In + Linux-PAM 0.75 pam_setcred() returns the last saved return code, + not the return code for the setcred module. Because we haven't + called pam_authenticate(), this is not set and so pam_setcred() + returns PAM_PERM_DENIED. + +2002-01-19 19:43 millert + + * Makefile.binary, Makefile.in: Don't need a '/' between $(DESTDIR) + and a directory. + +2002-01-18 14:18 millert + + * configure: regen + +2002-01-18 14:18 millert + + * configure.in: o BSDi also has a bogus setreuid() o Old FreeBSD + has a bogus setreuid() o new NetBSD has a real setreuid() o add + check for freeifaddrs() if getifaddrs() exists. + +2002-01-18 14:17 millert + + * config.h.in, interfaces.c: Older BSDi releases lack freeifaddrs() + so add a test for that and if it is not present just use free(). + +2002-01-17 11:30 millert + + * CHANGES, RUNSON: Checkpoint for 1.6.5p1 + +2002-01-17 10:56 millert + + * auth/passwd.c: Return AUTH_FAILURE in passwd_init() if + skeyaccess() denies access to normal passwords, not AUTH_FATAL + (which just causes an exit). + +2002-01-17 10:35 millert + + * visudo.c: Don't use memory after it has been freed. + +2002-01-17 00:24 millert + + * auth/passwd.c: skeyaccess() wants a struct passwd * not a char *; + Patch from Phillip E. Lobbes + +2002-01-16 20:00 millert + + * BUGS: ++version + +2002-01-16 19:53 millert + + * CHANGES, RUNSON, TODO: checkpoint for sudo 1.6.5 + +2002-01-16 18:37 millert + + * configure: regen + +2002-01-16 18:37 millert + + * INSTALL, INSTALL.binary, Makefile.in, README, configure.in: + version 1.6.5 + +2002-01-16 18:37 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat, + visudo.man.in: sudo version 1.6.5 + +2002-01-16 16:28 millert + + * logging.c: o when invoking the mailer as root use a hard-coded + environment that doesn't include any info from the user's + environment. Basically paranoia. + + o Add support for the NO_ROOT_MAILER compile-time option and run + the mailer as the user and not root if NO_ROOT_MAILER is + defined. + +2002-01-16 16:27 millert + + * set_perms.c, sudo.h: Bring back PERM_FULL_USER + +2002-01-16 16:26 millert + + * configure: regen + +2002-01-16 16:26 millert + + * version.h: version 1.6.5 + +2002-01-16 16:26 millert + + * INSTALL, config.h.in, configure.in: Add --disable-root-mailer + option to run the mailer as the user and not root. + +2002-01-16 12:44 millert + + * CHANGES: checkpoint for 1.6.4p2 + +2002-01-15 19:22 millert + + * PORTING: Mention the "seteuid(0): Operation not permitted" + problem here too just for good measure. + +2002-01-15 18:43 millert + + * env.c, getspwuid.c, sudo.c: The SHELL environment variable was + preserved from the user's environment instead of being reset + based on the passwd database when the "env_reset" option was + used. Now it is reset as it should be. + +2002-01-15 17:47 millert + + * configure: regen + +2002-01-15 17:47 millert + + * INSTALL, TROUBLESHOOTING, config.h.in, configure.in, set_perms.c, + sudo.c: Add a configure option to turn off use of POSIX saved IDs + +2002-01-15 15:48 millert + + * configure: regen + +2002-01-15 15:48 millert + + * configure.in: add --with-efence option + +2002-01-15 15:39 millert + + * sudo.c: Only OR in MODE_RESET_HOME if MODE_RUN is set. Fixes a + problem where "sudo -l" would not work if always_set_home was + set. + +2002-01-15 13:16 millert + + * lex.yy.c: regen + +2002-01-15 13:16 millert + + * parse.lex: Quoted commas were not being treated correctly in + command line arguments. + +2002-01-14 20:53 millert + + * sudo.c: o Move the call to rebuild_env() until after + MODE_RESET_HOME is set. Otherwise, the set_home option has no + effect. + + o Fix use of freed memory when the "fqdn" flag is set. This was + introduced by the fix for the "segv when gethostbynam() fails" + bug. Also, we no longer call set_fqdn() if the "fqdn" flag is + not set so there is no need to check the "fqdn" flag in + set_fqdn() itself. + +2002-01-14 20:45 millert + + * env.c: Add 'continue' statements to optimize the switch + statement. From Solar. + +2002-01-13 13:42 millert + + * sudoers.cat, sudoers.man.in: Regen from new sudoers.pod + +2002-01-13 13:36 millert + + * sudoers.pod: Add caveat about stay_setuid flag + +2002-01-13 13:29 millert + + * sudo.c: If set_perms == set_perms_posix and the stay_setuid flag + is not set, set all uids to 0 and use set_perms_fallback(). + +2002-01-13 13:28 millert + + * set_perms.c, sudo.h: Remove PERM_FULL_USER (which is no longer + used) and add PERM_FULL_ROOT (used when exec'ing the mailer). + +2002-01-13 13:27 millert + + * logging.c: Use set_perms(PERM_FULL_ROOT, 0) before exec'ing the + mailer since we never want to run the mailer setuid. + +2002-01-12 17:55 millert + + * sudo.cat, sudo.man.in, sudo.pod, visudo.cat, visudo.man.in, + visudo.pod: Use sudo.ws instead of courtesan.com in URLs + +2002-01-12 14:00 millert + + * Makefile.in, Makefile.binary: Fix mansect substitution + +2002-01-12 13:15 millert + + * Makefile.in: Substitute man sections in Makefile.binary + +2002-01-12 13:15 millert + + * Makefile.binary: Sync install targets with Makefile.in and + substitute in man sections. + +2002-01-12 13:09 millert + + * INSTALL, INSTALL.binary: version is 1.6.4 + +2002-01-12 12:59 millert + + * Makefile.in: Repair bindist target + +2002-01-12 11:43 millert + + * CHANGES: sync for 1.6.4 + +2002-01-10 13:00 millert + + * install-sh: Fix case where neither whoami nor id are found + +2002-01-09 12:35 millert + + * install-sh: If neither whoami nor id exists, just assume we are + root. + +2002-01-09 11:56 millert + + * alloc.c: Add explicit cast to (VOID *) on malloc/realloc. Seems + to be needed on AIX which for some reason isn't pulling in the + malloc prototype. + +2002-01-08 10:00 millert + + * Makefile.in, aclocal.m4, compat.h, parse.c, sudo.c: (c) 2002 + +2002-01-08 09:21 millert + + * CHANGES: checkpoint + +2002-01-08 09:20 millert + + * sudo.c: Defer assigning new environment until right before the + exec. + +2002-01-08 09:08 millert + + * parse.c: kill extra blank line + +2002-01-07 13:59 millert + + * configure: regen + +2002-01-07 13:59 millert + + * configure.in: Use -O not -O2 for m88k-motorola-sysv* since + motorola gcc-derived compiler doesn't recognise -O2. + +2002-01-06 23:02 millert + + * HISTORY: Clarify origins of Root Group sudo a bit based on info + from billp@rootgroup.com + +2002-01-02 22:41 millert + + * LICENSE: 2002 + +2002-01-02 22:26 millert + + * CHANGES: checkpoint for 1.6.4rc1 + +2002-01-02 17:40 millert + + * config.h.in: now generated via autoheader + +2002-01-02 17:40 millert + + * configure: regen + +2002-01-02 17:37 millert + + * compat.h: Move in some stuff that was previously in config.h. + +2002-01-02 17:36 millert + + * configure.in, aclocal.m4: Add info for autoheader. + +2002-01-01 16:53 millert + + * Makefile.in: o Add DESTDIR support + o Use -M, -O, and -G instead of -m, -o, and -g to facilitate + non-root installs + +2002-01-01 16:48 millert + + * install-sh: Add -M option (like -m but only for root) If we can't + find "whoami", use "id" w/ some sed. + +2002-01-01 14:01 millert + + * configure: regen + +2002-01-01 14:00 millert + + * configure.in: allow user to always override mansectsu and + mansectform + +2001-12-31 17:05 millert + + * mkinstalldirs: update from autoconf 2.52 + +2001-12-31 17:03 millert + + * config.guess, config.sub: Update from autoconf 2.52 + +2001-12-31 16:57 millert + + * configure: regen with autoconf 2.52 + +2001-12-31 16:57 millert + + * configure.in: o Call AC_PROG_CC_STDC to find out how to run the + compiler in ANSI mode + o Remove compiler-specific checks for HP-UX now that we use + AC_PROG_CC_STDC + +2001-12-31 12:19 millert + + * RUNSON: Checkpoint + +2001-12-31 12:18 millert + + * auth/pam.c: o Add pam_prep_user function to call pam_setcred() + for the target user; on Linux this often sets resource limits. + o When calling pam_end(), try to convert the auth->result to a + PAM_FOO value. This is a hack--we really need to stash the + last PAM_FOO value received and use that instead. + +2001-12-31 12:18 millert + + * set_perms.c, sudo.h: o Add pam_prep_user function to call + pam_setcred() for the target user; on Linux this often sets + resource limits. + +2001-12-31 00:53 millert + + * env.c: Fix off by one error in number of bytes allocated via + malloc (does not affected any released version of sudo). + +2001-12-30 17:12 millert + + * lex.yy.c: regen + +2001-12-30 17:12 millert + + * parse.lex: Allow '@', '(', ')', ':' in arguments to a defaults + variable w/o requiring that they be quoted. + +2001-12-30 14:26 millert + + * sudoers.cat, sudoers.man.in, sudoers.pod: Mention that no double + quotes are needed when adding/deleting/assigning a single value + to a list. + +2001-12-30 13:58 millert + + * Makefile.in: Don't rely on mkdefaults being executable, call perl + explicitly. + +2001-12-30 13:41 millert + + * parse.yacc: Remove some XXX that are no longer relevant. + +2001-12-30 13:40 millert + + * defaults.c: o Roll our own loop instead of using strpbrk() for + better grokability o When adding to a list we must malloc() and + use memcpy(), not strdup() since we must only copy len bytes + from str. + +2001-12-21 16:49 millert + + * parse.yacc: typo in comment + +2001-12-19 11:50 millert + + * CHANGES: checkpoint + +2001-12-19 10:56 millert + + * configure: regen + +2001-12-19 10:56 millert + + * configure.in: avoid the -g flag unless --with-devel was specified + +2001-12-19 10:04 millert + + * Makefile.in: mkdefaults, def_data.in and sigaction.c were missing + from the tarball + +2001-12-19 09:46 millert + + * Makefile.in: def_data.c was missing + +2001-12-18 12:42 millert + + * env.c: Fix setting of $USER and $LOGNAME in the non-reset_env + case. Also allow HOME, SHELL, LOGNAME, and USER to be specified + in keep_env + +2001-12-17 20:48 millert + + * TODO: Another TODO item + +2001-12-17 19:50 millert + + * sudoers: Add comment for Default section so folks know where it + should go. + +2001-12-17 18:56 millert + + * tgetpass.c: Use TCSETAF, not TCSETA to set terminal in termio + case + +2001-12-17 18:35 millert + + * sudoers.man.in, sudoers.cat: regen from sudoers.pod + +2001-12-17 18:33 millert + + * sudoers.pod: o Typo, Runas_User_List should be Runas_List + o a User_List can not contain a uid + o mention that the Defaults section should come after Alias + definitions but before the user specifications + +2001-12-15 11:51 millert + + * sudoers.cat, sudoers.man.in: regen + +2001-12-15 11:51 millert + + * sudoers.pod: Fix listpw and verifypw sections, they were not + being formatted properly. + +2001-12-15 11:39 millert + + * sudoers.cat, sudoers.man.in: regen + +2001-12-15 11:38 millert + + * sudoers.pod: fix typos + +2001-12-15 10:57 millert + + * configure: regen + +2001-12-15 10:57 millert + + * configure.in, config.h.in: use AC_SYS_POSIX_TERMIOS instead of + rolling our own + +2001-12-15 10:33 millert + + * README: Reference sudo.ws not courtesan.com + +2001-12-15 10:29 millert + + * PORTING: Add notes on shadow passwords + +2001-12-15 00:48 millert + + * BUGS: In list mode (sudo -l), characters escaped with a backslash + are shown verbatim with the backslash. + +2001-12-15 00:44 millert + + * sudoers: Add simple examples from OpenBSD (Marc Espie) + +2001-12-15 00:40 millert + + * tgetpass.c: Catch SIGTTIN and SIGTTOU too and treat them like + SIGTSTP. + +2001-12-14 21:53 millert + + * CHANGES: minor prettyification + +2001-12-14 21:43 millert + + * CHANGES: Updated change log + +2001-12-14 21:27 millert + + * testsudoers.c: Fix CIDR handling here too. + +2001-12-14 21:21 millert + + * auth/pam.c: Apparently a NULL response is OK + +2001-12-14 21:19 millert + + * TODO: Checkpoint for upcoming beta release + +2001-12-14 21:17 millert + + * TROUBLESHOOTING: Many people believe that adding a runas spec + should obviate the need for the -u flag. It does not. + +2001-12-14 21:11 millert + + * RUNSON: checkpoint update for upcoming 1.6.4 beta + +2001-12-14 20:44 millert + + * config.h.in: o Add HAVE_STDLIB_H and HAVE_MEMORY_H o Define + HAVE_STRINGS_H even if HAVE_STRING_H is defined -- this is safe + now + +2001-12-14 20:07 millert + + * PORTING: Add signals section + +2001-12-14 20:00 millert + + * configure: regen + +2001-12-14 20:00 millert + + * configure.in: Fix check for sigaction_t + +2001-12-14 19:45 millert + + * sudo.c: XXX - should call find_path() as runas user, not root. + Can't do that until the parser changes though. + +2001-12-14 19:38 millert + + * sudo.c: If find_path() fails as root, try again as the invoking + user (useful for NFS). Idea from Chip Capelik. + +2001-12-14 19:28 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in: Regenerate + after pod file changes + +2001-12-14 19:24 millert + + * def_data.c, def_data.h, def_data.in, set_perms.c, sudo.c, sudo.h, + sudo.pod, sudoers.pod: Add new sudoers option "preserve_groups". + Previously sudo would not call initgroups() if the target user + was root. Now it always calls initgroups() unless the -P command + line option or the "preserve_groups" sudoers option is set. Idea + from TJ Saunders. + +2001-12-14 18:38 millert + + * compat.h, config.h.in: Use new HAVE_SIGACTION_T define + +2001-12-14 18:33 millert + + * logging.c: Fix compilation on K&C + +2001-12-14 18:14 millert + + * configure: regen + +2001-12-14 18:14 millert + + * configure.in: Add check for sigaction_t -- IRIX already defines + this so don't redefine it. + +2001-12-14 17:15 millert + + * snprintf.c: fix typo + +2001-12-14 17:12 millert + + * interfaces.c: need stdlib.h here too + +2001-12-14 15:31 millert + + * configure: regen + +2001-12-14 15:31 millert + + * configure.in: Remove redundant checks for string.h, strings.h and + unistd.h + +2001-12-14 15:29 millert + + * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in, visudo.cat, + visudo.man.in: Regen from pod files + +2001-12-14 15:03 millert + + * BUGS: Update for 1.6.4 + +2001-12-14 14:59 millert + + * configure, lex.yy.c: regen + +2001-12-14 14:56 millert + + * strerror.c: Return EINVAL if errnum > sys_nerr + +2001-12-14 14:54 millert + + * LICENSE, Makefile.binary, Makefile.in, aclocal.m4, compat.h, + config.h.in, defaults.h, interfaces.h, pathnames.h.in, sudo.h, + sudo.pod, auth/sudo_auth.h: o Update copyright year + +2001-12-14 14:54 millert + + * configure.in: o Don't define STDC_HEADERS unconditionally for + IRIX o Update copyright year + +2001-12-14 14:53 millert + + * README: update version + +2001-12-14 14:52 millert + + * alloc.c, check.c, defaults.c, env.c, fileops.c, find_path.c, + fnmatch.c, getcwd.c, getspwuid.c, goodpath.c, interfaces.c, + logging.c, lsearch.c, parse.c, parse.lex, parse.yacc, + set_perms.c, snprintf.c, sudo.c, testsudoers.c, tgetpass.c, + utime.c, visudo.c, 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/sia.c, auth/sudo_auth.c: o Reorder some headers and use + STDC_HEADERS define properly o Update copyright year + +2001-12-14 01:53 millert + + * configure: regen + +2001-12-14 01:53 millert + + * tgetpass.c: flags set in signal handlers should be volatile + sig_atomic_t + +2001-12-14 01:52 millert + + * config.h.in, configure.in: Add checks for volatile and + sig_atomic_t + +2001-12-14 01:42 millert + + * lex.yy.c, configure: regen + +2001-12-14 01:40 millert + + * def_data.c, def_data.h, def_data.in, defaults.c, env.c, + find_path.c, sudo.c, sudoers.pod: Remove "secure_path" Defaults + option since it cannot work with the existing parser. + +2001-12-14 01:26 millert + + * find_path.c, sudo.c: Unset "secure_path" if user_is_exempt() + +2001-12-14 01:24 millert + + * env.c, pathnames.h.in: o Remove assumption that PATH and TERM are + not listed in env_keep o If no PATH is in the environment use a + default value o If TERM is not set in the non-reset case also + give it a default value. + +2001-12-14 01:17 millert + + * aclocal.m4, configure.in, defaults.c, pathnames.h.in: + _PATH_SENDMAIL -> _PATH_SUDO_SENDMAIL so --without-sendmail works + on systems that define in paths.h + +2001-12-14 01:15 millert + + * auth/: passwd.c, sudo_auth.c, sudo_auth.h: Add support for + skeyaccess(3) if it is present in libskey. + +2001-12-12 21:42 millert + + * sudo.c: Only need to do 'lc = login_getclass(NULL)' if lc == NULL + +2001-12-12 21:24 millert + + * parse.lex: '\\' is a perfectly legal character to have in a + command line argument. + +2001-12-12 20:24 millert + + * sudo.c: o Defer call to set_fqdn() until it is safe to use + log_error() o Don't print errno string value if gethostbyname + fails, it is not relevant + +2001-12-12 20:07 millert + + * parse.c: Fix CIDR -> in_addr_t conversion. + +2001-12-12 16:21 millert + + * sudoers.pod: Remove an extra "User_List" in the User_Spec + definition From ybertrand AT snoopymail.com + +2001-12-12 16:00 millert + + * parse.c: Make 'listpw=never' work for users who are not + explicitly mentioned in sudoers. + +2001-12-12 15:40 millert + + * sudoers.pod: Remove gratuitous '=' in EBNF grammar; era AT iki.fi + +2001-12-12 15:34 millert + + * sudoers.pod: Document new list Defaults type and convert env_keep + and env_delete to lists. Document new env_check option. + +2001-12-12 15:11 millert + + * lex.yy.c, sudo.tab.h: regen parser + +2001-12-12 14:56 millert + + * parse.lex: Don't let '#' appear in a {WORD} and restrict #foo in + a Runas spec to #[0-9-]+. + +2001-12-12 14:55 millert + + * configure: regen + +2001-12-12 14:55 millert + + * aclocal.m4: Simpler SUDO_FUNC_ISBLANK that uses AC_TRY_LINK + +2001-12-12 14:43 millert + + * config.h.in, configure.in: Add check for skeyaccess(3) + +2001-12-11 19:47 millert + + * visudo.pod: Document new -c, -f, and -q options + +2001-12-11 19:41 millert + + * visudo.c: o Add -f option (alternate sudoers file) o Convert to + use getopt(3) + +2001-12-11 19:31 millert + + * configure: regen + +2001-12-11 19:31 millert + + * aclocal.m4, config.h.in, configure.in: Add check for isblank and + a replacement macro if it doesn't exist. + +2001-12-11 18:22 millert + + * visudo.c: In check-only mode, don't create sudoers if it does not + already exist. + +2001-12-11 18:06 millert + + * parse.yacc: o Add a new token, DEFVAR, to indicate a Defaults + variable name + o Add support for "+=" and "-=" list operators + o replace some 1 and 0 with TRUE and FALSE for greater + legibility. + +2001-12-11 18:05 millert + + * parse.lex: o Use exclusive start conditions to remove some + ambiguity in the + lexer. Also reorder some things for clarity. + o Add support for "+=" and "-=" list operators. + o Use the new DEFVAR token to denote a Defaults variable name. + +2001-12-11 18:03 millert + + * sudo.h: Prototype init_envtables() + +2001-12-11 18:02 millert + + * env.c: o Convert environment handling to use lists instead of + strings. + This greatly simplifies routines that need to do "foreach" + type + operations. + o Add new init_envtables() function to set env_check and + env_delete + defaults based on initial_badenv_table and + initial_checkenv_table + (formerly sudo_badenv_table). + +2001-12-11 18:00 millert + + * defaults.c, defaults.h: o Add a new LIST type and functions to + manipulate it. + o This is for use with environment handling variables. + o Call new init_envtables() routine inside init_defaults() to + initialize the environment lists. + +2001-12-11 17:57 millert + + * def_data.c, def_data.h, def_data.in: Convert environment options + to use the new LIST type and add a new one, env_check that only + deletes if the sanity check fails. + +2001-12-11 17:55 millert + + * testsudoers.c: Add dummy version of init_envtables() + +2001-12-11 17:53 millert + + * parse.yacc: honor quiet mode + +2001-12-11 17:51 millert + + * visudo.c: Add check-only mode + +2001-12-10 20:27 millert + + * mkdefaults: Fix generation of entries with NULL descriptions. + +2001-12-09 00:27 millert + + * tgetpass.c: Use sigaction_t and quiet a gcc warning. + +2001-12-09 00:20 millert + + * sudo.c: Must reset signal handlers before we exec + +2001-12-09 00:16 millert + + * auth/: aix_auth.c, bsdauth.c, fwtk.c, pam.c, sudo_auth.c: Be + carefule now that tgetpass() can return NULL (user hit ^C). PAM + version needs testing. Set SIGTSTP to SIG_DFL during password + entry so user can suspend us. + +2001-12-09 00:14 millert + + * tgetpass.c: Add support for interrupting/suspending tgetpass via + keyboard input. If you suspend sudo from the password prompt and + resume it will re-prompt you. + +2001-12-09 00:09 millert + + * sudo.c: Don't block keyboard interrupt signals, just set them to + SIG_IGN. + +2001-12-08 14:48 millert + + * config.h.in: add back HAVE_SIGACTION + +2001-12-08 14:44 millert + + * configure: regen + +2001-12-08 14:44 millert + + * config.h.in, configure.in, logging.c, sudo.c, visudo.c: Kill + POSIX_SIGNALS define and old signal support now that we emulate + POSIX ones Also be sure to correctly initialize struct sigaction. + +2001-12-08 14:42 millert + + * strerror.c: Don't need config.h or "#ifndef HAVE_STRERROR" + wrapper. + +2001-12-08 14:39 millert + + * compat.h: Add scaffolding for POSIX signal emulation + +2001-12-08 14:36 millert + + * sigaction.c: o Add missing ';' so this compiles o Can't use NULL + since we don't include stdio.h + +2001-12-08 14:23 millert + + * sigaction.c: Emulate sigaction() using sigvec() + +2001-11-12 19:32 millert + + * sudoers.pod: Document new behavior of negative values of + timestamp_timeout Fix a typo + +2001-11-12 19:31 millert + + * sudo.pod: Add security note about command not being logged after + 'sudo su' and friends. + +2001-11-12 19:19 millert + + * sudo.pod: Mention that -V prints default values when run as root, + including the list of environment variables to clear. + +2001-11-12 19:14 millert + + * Makefile.in: Run pod2man with --quotes=none to avoid stupid + quoting of C<> entries. + +2001-11-12 13:12 millert + + * def_data.c, def_data.h, def_data.in, sudoers.pod, + auth/sudo_auth.c: Add mail_badpass option Also modify mail_always + behavior to also send mail when the password is wrong + +2001-11-12 13:08 millert + + * env.c, sudo.c, sudo.h: Dump default bad env table when 'sudo -V' + is run by root. + +2001-11-11 23:52 millert + + * sudoers.pod: document env_delete + +2001-11-11 23:51 millert + + * env.c: Add support for '*' in env_keep when not resetting the + environment (ie: the normal case). + +2001-11-11 23:47 millert + + * env.c: Add env_delete variable that lets the user replace/add to + the bad_env_table. Allow '*' wildcard in env_keep entries. + +2001-11-06 13:59 millert + + * mkinstalldirs: Force umask to 022 to guarantee sane directory + permissions. + +2001-11-02 18:09 millert + + * Makefile.in: add sudo.tab.h and sudo.tab.c to sudo.tab.o + dependency + +2001-11-02 17:25 millert + + * mkdefaults: fix breakage in last commit + +2001-11-02 17:18 millert + + * Makefile.in: acsite.m4 -> aclocal.m4 + +2001-11-02 15:59 millert + + * check.c: fix I_TS_TIMEOUT vs. I_TIMESTAMP_TIMEOUT pasto in + previous commit + +2001-11-02 15:57 millert + + * def_data.c: regenerated from def_data.in + +2001-11-02 15:56 millert + + * check.c, defaults.c, defaults.h: Add new T_UINT type that most + things use instead of T_INT If timestamp_timeout is < 0 then + treat the ticket as never expiring (to be expired manually by the + user). + +2001-11-02 15:51 millert + + * def_data.in: change most T_INT -> T_UINT + +2001-11-02 15:51 millert + + * mkdefaults: fix warning when no args + +2001-11-02 12:52 millert + + * visudo.c: Change 2 Exit() -> exit() Avoid stdio in Exit() and + call _exit() if we are a signal handler. We no longer print the + signal number but the user can just check the exit value for + that. + +2001-10-16 01:35 millert + + * logging.c: when setting up pipes in child process check for case + where stdin == pipe fd 0 + +2001-10-11 13:20 millert + + * visudo.c: Ignore editor exit value since XPG4 says vi's exit + value is the count of editing errors made (failed searches, etc). + +2001-10-05 16:39 millert + + * configure: regen + +2001-10-05 16:39 millert + + * configure.in: sco now is identified by config.guess as *-sco-* + +2001-10-05 16:24 millert + + * configure.in: Check for getspnam() in -lgen if not in -lc for + UnixWare. + +2001-09-17 21:48 millert + + * sudoers.pod, visudo.pod: "upper case" -> "uppercase" + +2001-09-17 21:32 millert + + * sudoers.pod: fix typos and grammar; pjanzen@foatdi.harvard.edu + +2001-08-28 10:26 millert + + * sudoers.pod: Missing word (specify); krapht@secureops.com + +2001-08-23 17:43 millert + + * sudo.c: If we fail to lookup a login class, apply the default + one. + +2001-08-23 17:42 millert + + * logging.c: In log_error() free message, not logline + unconditionally, then free logline if it is not the same as + message. No function change but this mirrors how they are + allocated. + +2001-07-16 23:33 millert + + * configure: regenerate + +2001-07-16 23:33 millert + + * configure.in: remove some backslash quotes that are unneeded + +2001-07-16 23:30 millert + + * configure.in: o Tweaks to make this work with autoconf-2.50 o Use + AC_LIBOBJ instead of changing LIBOBJS directly o Use + AC_REPLACE_FUNCS where we can o Use AC_CHECK_FUNCS instead of + AC_CHECK_FUNC so we don't have to AC_DEFINE things manually. + +2001-07-16 23:28 millert + + * config.guess, config.sub: Updated from autoconf-2.50 + +2001-05-22 19:11 millert + + * README: Update mailing list section. We use mailman now, not + majordomo. + +2001-05-10 14:55 millert + + * getspwuid.c, logging.c, sudo.c: Use setpwent()/endpwent() + all + the shadow variants to make sure we don't inadvertantly leak an + fd to the child. Apparently Linux's shadow routines leave the fd + open even if you don't call setspent(). Reported by + mike@gistnet.com; different patch used. + +2001-04-12 21:43 millert + + * sudoers.pod: s/eg./e.g./ + +2001-04-12 21:42 millert + + * tgetpass.c: select() may return EAGAIN. If so, continue like we + do for EINTR. + +2001-04-12 21:41 millert + + * logging.c: Fix a non-exploitable buffer overflow in the word + splitting code. This should really be rewritten. + +2001-04-12 21:41 millert + + * Makefile.in: FAQ link goes away + +2001-04-12 21:40 millert + + * INSTALL: Tell people to look in sample.syslog.conf for examples, + not FAQ + +2001-04-12 21:40 millert + + * TROUBLESHOOTING: Update list of env vars that are cleared + +2001-04-12 21:36 millert + + * sudo.c: remove struct env_table decl since that stuff has all + moved to env.c + +2001-04-04 13:17 millert + + * fileops.c: Fix a pasto in flock-style unlocking and include + for flock on older systems; twetzel@gwdg.de + +2001-04-04 13:14 millert + + * configure: regen to get NeXT lockf/flock fix + +2001-04-04 13:14 millert + + * configure.in: force NeXT to use flock since lockf is broken + +2001-03-30 08:54 millert + + * check.c: Use stashed user_gid when checking against exempt gid + since sudo sets its gid to a a value that makes sudoers readable. + Previously if you used gid 0 as the exempt group everyone would + be exempt. From Paul Kranenburg + +2001-03-29 13:14 millert + + * configure: regen + +2001-03-29 13:08 millert + + * aclocal.m4: #include stdio.h in SUDO_CHECK_TYPE since IRIX 6 + aparently defines some types (such as ssize_t) therein. + +2001-03-02 09:09 millert + + * defaults.c: Fix negation of paths in a boolean context. Problem + found by apt@UH.EDU + +2001-02-23 13:03 millert + + * visudo.c: pasto + +2001-02-17 16:11 millert + + * visudo.c: SA_RESETHAND means the opposite of what I was + thinking--oops To block all signals in old-style signals use ~0, + not 0xffffffff + +2001-02-04 11:16 millert + + * defaults.c: coerce difference of pointers to int when used in a + string length printf format; deraadt@openbsd.org + +2001-01-17 11:34 millert + + * visudo.c: Block all signals in Exit() to avoid a signal race. + There is still a tiny window but I'm not going to worry about it. + +2001-01-07 13:57 millert + + * env.c: glibc uses the LANGUAGE env var so clear that too; Solar + Designer + +2001-01-07 13:55 millert + + * lex.yy.c: Regenerate with a fix to flex.skl that preserves errno + from clobbering by isatty(). + +2000-12-30 20:39 millert + + * auth/: aix_auth.c, bsdauth.c, fwtk.c, pam.c, sia.c, sudo_auth.c: + Some defaults I_ defines got renamed. + +2000-12-30 20:38 millert + + * Makefile.in, check.c, def_data.c, def_data.h, def_data.in, + defaults.c, defaults.h, env.c, logging.c, mkdefaults, parse.yacc, + set_perms.c, sudo.c: Move defaults info into its own files from + which we generate .h and .c files. This makes adding or + rearranging variables much simpler. + +2000-12-30 16:58 millert + + * configure, configure.in: fix typo in last commit + +2000-12-30 16:55 millert + + * compat.h, config.h.in, configure, configure.in: Add check + + emulation for setegid (like seteuid). + +2000-12-30 16:22 millert + + * env.c: Make env_keep override badenv_table as documented Fix + traversal of badenv_table (broken in last commit) + +2000-12-29 22:59 millert + + * set_perms.c, sudo.c, sudo.h: Don't try and build saved uid + version of set_perms on systems w/o them. Rename + set_perms_saved_uid() -> set_perms_posix() Make + set_perms_setreuid simply be set_perms_fallback() and simply + include the appropriate function at compile time (setreuid() + vs. setuid()). + +2000-12-29 22:45 millert + + * sudoers.pod, sudoers.cat, sudoers.man.in: PATH is also preserved + when env_reset is in effect + +2000-12-29 22:29 millert + + * CHANGES, env.c, Makefile.in, check.c, compat.h, config.h.in, + configure, configure.in, defaults.c, defaults.h, find_path.c, + getspwuid.c, set_perms.c, sudo.c, sudo.cat, sudo.h, sudo.man.in, + sudo.pod, sudoers.cat, sudoers.man.in, sudoers.pod, + testsudoers.c, visudo.c, visudo.cat, visudo.man.in: New Defaults + options: o stay_setuid - sudo will remain setuid if system has + saved uids or setreuid(2) o env_reset - reset the environment to + a sane default o env_keep - preserve environment variables that + would otherwise be cleared + + No longer use getenv/putenv/setenv functions--do environment + munging by hand. Potentially dangerous environment variables can + be cleared only if they contain '/' pr '%' characters to protect + buggy programs. Moved environment routines into env.c (new file) + +2000-12-29 22:17 millert + + * INSTALL: Clear up --without-passwd description + +2000-12-29 19:39 millert + + * sudo_setenv.c, putenv.c: We now build up a new environment from + scratch and assign it to "environ". + +2000-12-18 22:35 millert + + * sudo.pod, visudo.pod: Grammatical fixes from Paul Janzen + +2000-12-14 23:19 millert + + * visudo.c: If there was a syntax error and the user just wants to + quit, unlink sudoers if it is zero length. + +2000-12-14 23:10 millert + + * visudo.c: 'Q' means ignore parse error, not 'q' + +2000-12-14 22:57 millert + + * visudo.c: Open sudoers for writing with mode SUDOERS_MODE From + Dimitry Andric + +2000-12-13 12:23 millert + + * set_perms.c: Add missing #ifdef HAVE_LOGIN_CAP_H; + ayamura@ayamura.org + +2000-12-09 11:46 millert + + * config.guess, config.sub: Darwin / Mac OS X support from Wilfredo + Sanchez + +2000-11-03 09:36 millert + + * sudo.c, visudo.c: Use exit(127), not exit(-1) + +2000-11-03 00:37 millert + + * defaults.h, set_perms.c, sudo.c, Makefile.in, defaults.c: Move + set_perms() to its own file and use POSIX saved uid or setreuid() + if available. + + Added stay_setuid option for systems that have libraries that + perform extra paranoia checks in system libraries for setuid + programs (ie: anything with issetugid(2)). + +2000-11-02 20:28 millert + + * sudo.c: strip more bits from the environment and add a facility + for stripping things only if they contain '/' or '%' to address + printf format string vulnerabilities in other programs. + +2000-11-02 12:55 millert + + * configure: regen + +2000-11-02 12:55 millert + + * configure.in: For NCR, add -lc89 to LIBS, not SUDO_LIBS and cache + the existence of strcasecmp(). + +2000-11-02 12:46 millert + + * configure: regen + +2000-11-02 12:46 millert + + * configure.in: Check for strcasecmp(3) in -lc89 for NCR Unix + +2000-11-01 10:22 millert + + * config.h.in: Define HAVE_INNETGR #ifdef HAVE__INNETGR + +2000-11-01 10:17 millert + + * configure: regen + +2000-11-01 10:17 millert + + * compat.h, config.h.in, configure.in: Add check for _innetgr(3) + since NCR systems have that instead of innetgr(3). + +2000-10-31 14:16 millert + + * auth/securid.c: check return value of creadcfg() call sd_close() + after sd_auth() store username in sd->username so we don't rely + on the USER env variable + +2000-10-29 23:00 millert + + * INSTALL: document --with-bsdauth + +2000-10-29 22:57 millert + + * configure: regen + +2000-10-29 22:56 millert + + * configure.in: --with-bsdauth assumes --with-logincap + +2000-10-29 22:45 millert + + * auth/: bsdauth.c, fwtk.c: When prompting for a response to a + challenge, if the user just hits return then reprompt with echo + turned on. + +2000-10-29 17:31 millert + + * sudo.c: Remove debugging code that should not have been + committed, oops. + +2000-10-29 17:31 millert + + * auth/bsdauth.c: Use lower-level routines and get the password + ourselves. Checks for a challenge and if there is one echo is + not turned off. + +2000-10-29 17:30 millert + + * auth/: pam.c, sudo_auth.h: minor housekeeping, no real code + changes + +2000-10-27 18:41 millert + + * sudo.c: Fix a coredump in the logging functions if gethostname(2) + fails by deferring the call to log_error() until things are + better setup. + + Fix return value of set_loginclass() in non-BSD-auth case. + + Hard-code 'sudo' in the usage message so we can fit more options + on a line + +2000-10-27 18:35 millert + + * logging.c: Fix errant ';' (typo) that broken MSG_ONLY + +2000-10-26 13:03 millert + + * sudo.cat, sudo.man.in: regen + +2000-10-26 13:01 millert + + * sudo.pod: Document -a flag + +2000-10-26 12:42 millert + + * Makefile.in, config.h.in, configure, configure.in, getspwuid.c, + sudo.c, auth/sudo_auth.h, auth/bsdauth.c: Add support for BSD + authentication. + +2000-10-19 10:09 millert + + * sudoers.pod: Fix typo; from sato@complex.eng.hokudai.ac.jp + +2000-10-12 09:49 millert + + * sudoers.pod: Mention negating umask + +2000-10-12 01:30 millert + + * defaults.c: Allow user to specify umask of 0777 (same as !umask) + +2000-10-08 21:46 millert + + * sudo.pod, visudo.pod: Fix a typo and give a URL for the sudo + history. + +2000-10-08 12:25 millert + + * defaults.c, sudo.pod: fix typos; pepper@reppep.com + +2000-09-14 16:48 millert + + * sudo.c, sudo.h, sudo_setenv.c: sudo_setenv() now exits on memory + alloc failure instead of returning -1. + +2000-09-07 17:41 millert + + * sudo.c: Strip out NLSPATH and PATH_LOCALE from the environment + for FreeBSD and possibly others. + +2000-09-07 10:43 millert + + * logging.c: Don't use vsyslog(3) since HP-UX (and others?) lack + it. This means that "%m" won't be expanded but we don't use that + anyway since the logging routines may splat to stderr as well. + +2000-09-06 21:35 millert + + * defaults.c, defaults.h, sudo.c, sudoers.cat, sudoers.man.in, + sudoers.pod: Add always_set_home variable + +2000-09-06 21:24 millert + + * configure, configure.in: Have to hard code default values in help + since the defaults are set _after_ the help stuff. + +2000-08-31 13:08 millert + + * lex.yy.c, parse.lex: Allow special characters (including '#') to + be embedded in pathnames if quoted by a '\\'. The quoted chars + will be dealt with by fnmatch(). Unfortunately, 'sudo -l' still + prints the '\\'. + +2000-08-13 17:10 millert + + * install-sh: Better path searching for programs we need. + +2000-08-13 17:10 millert + + * TROUBLESHOOTING: Add section on "C compiler cannot create + executables" errors. + +2000-08-13 17:10 millert + + * Makefile.binary, Makefile.in, version.h: Crank version + +2000-08-13 17:09 millert + + * aclocal.m4, configure, configure.in, sudo.cat, sudo.man.in, + sudo.pod, sudoers.cat, sudoers.man.in, sudoers.pod, visudo.cat, + visudo.man.in, visudo.pod: Substitute values from configure into + man pages. + +2000-08-12 16:48 millert + + * parse.c, sudo.c: The listpw and verifypw sudoers options would + not take effect because the value of the default was checked + *before* sudoers was parsed. Instead of passing in the value of + PWCHECK_* to sudoers_lookup(), pass in the arg for def_ival() so + the check can be deferred until after sudoers is parsed. + +2000-08-11 15:41 millert + + * tgetpass.c: When writing prompt, no need to write the NUL as + well; hag@linnaean.org + +2000-06-09 12:25 millert + + * install-sh: When looking for chown, check in /sbin too + +2000-06-04 22:57 millert + + * visudo.c: Remove extraneous call to init_defaults() and set + runas_user to NULL betweem parses so init_defaults will reset it + each time, thus avoiding a reference to free()d data. + +2000-06-04 19:57 millert + + * config.h.in, interfaces.c, interfaces.h, sudo.c: Add support for + using getifaddrs() to get the list of ip addr / netmask pairs. + Currently IPv4-only. + +2000-06-04 19:51 millert + + * visudo.c: Add a missing check for UserEditor == NULL Add missing + '+' before line number when invoking editor to fix a syntax error + +2000-05-12 16:55 millert + + * sudo.c: Call clean_env very early in main() for paranoia's sake. + Idea from Marc Esipovich. + +2000-05-10 01:11 millert + + * sudo.h: Update proto for evasprintf and easprintf + +2000-05-10 01:10 millert + + * alloc.c: Make easprintf() and evasprintf() return an int. + +2000-05-10 00:56 millert + + * check.c: If the targetpw flag is set, use target username as part + of the timestamp path. If tty tickets are in effect cat the tty + and the target username with a ':' as the separator. + +2000-05-09 12:05 millert + + * auth/pam.c: Backout part of last change; setting PAM_USER to the + invoking user breaks things like targetpw. + +2000-05-09 11:52 millert + + * auth/pam.c: set tty and username via pam_set_item + +2000-05-09 11:42 millert + + * check.c, getspwuid.c, sudo.c, sudo.h, auth/sudo_auth.c: Fix root, + runas, and target authentication for non-passwd file auth + methods. + +2000-04-22 14:15 millert + + * sudo.pod, sudo.man.in, sudoers.man.in, sudoers.pod, visudo.pod, + sudo.cat, sudoers.cat, visudo.man.in, visudo.cat: Use B<-Z> not + C<-Z> for command line flags in all places. This is more + consistent and works around a bug in Pod::Man. + +2000-04-22 13:59 millert + + * sudoers.cat, sudoers.man.in, sudoers.pod: Fix an occurence of + 'semicolon' that should be 'colon' + +2000-04-19 15:30 millert + + * configure, configure.in: Fix --with-badpri help line + +2000-04-17 14:01 millert + + * defaults.c, logging.c, sudo.c: Bracket calls to syslog with an + openlog() and closelog() since some authentication methods (like + PAM) may do their own logging via syslog. Since we don't use + syslog much (usually just once per session) this doesn't really + incur a performance penalty. It also Fixes a SEGV with pam_kafs. + +2000-04-15 16:32 millert + + * sudo.c: Fix -H flag. runas_homedir is only valid after + set_perms(PERM_RUNAS, mode) + +2000-04-12 18:56 millert + + * INSTALL: Clarify the fact that insults are not enabled just by + including them in the binary. + +2000-04-07 10:39 millert + + * sudo.man.in, sudoers.man.in, visudo.man.in, sudo.cat, + sudoers.cat, visudo.cat: Regenerated with perl 5.6.0 pod2man + +2000-04-07 10:38 millert + + * Makefile.in: Give date string to pod2man since its default is + ugly and it ain't got no alibi. + +2000-04-07 10:27 millert + + * Makefile.in: Do section substitution on the output of pod2man and + remove hack needed for old pod2man. + +2000-04-07 10:26 millert + + * sudo.pod, sudoers.pod, visudo.pod: Put back real man sections, we + will do the substitution later. + +2000-04-02 11:44 millert + + * configure, configure.in: Don't bother checking for the path to vi + if user specified --with-editor + +2000-04-01 17:25 millert + + * CHANGES, visudo.c: Visudo now does its own fork/exec instead of + calling system(3). + +2000-04-01 16:23 millert + + * CHANGES, INSTALL, Makefile.in, sudoers.cat, sudoers.man.in, + sudoers.pod, visudo.c: Visudo now checks for the existence of an + editor and gives a sensible error if it does not exist. + + The path to the editor for visudo is now a colon-separated list + of allowable editors. If the user has $EDITOR set and it matches + one of the allowed editors that editor will be used. If not, the + first editor in the list that actually exists is used. + +2000-04-01 16:22 millert + + * sudo.pod, sudo.cat, sudo.man.in: Clear up confusion wrt sudo's + return value. + +2000-03-27 12:08 millert + + * Makefile.in: Strip sudo and visudo for bindist target + +2000-03-26 22:26 millert + + * sudo.cat, sudo.man.in, sudo.pod, sudoers.cat, sudoers.man.in, + sudoers.pod, visudo.cat, visudo.man.in, visudo.pod: Use + @mansectsu@ and @mansectform@ in the man page bodies as well. + +2000-03-26 22:07 millert + + * visudo.cat, visudo.man.in, visudo.pod: Typo: @sysconf@ -> + @sysconfdir@ + +2000-03-26 21:57 millert + + * Makefile.in: 'make dist' should not cause any files to be + modified so remove its dependencies. + +2000-03-26 21:43 millert + + * CHANGES: Whoops, forgot to add release marker + +2000-03-26 11:57 millert + + * CHANGES: Final change for 1.6.3 (or so I hope) + +2000-03-26 11:57 millert + + * sudo.cat, sudoers.cat, visudo.cat: Use SYSV man sections since + BSD systems will have nroff... + +2000-03-24 18:58 millert + + * parse.yacc: When checking to see if the host/user matches in a + defaults spec, check against TRUE, not just non-zero since it + might be -1. + +2000-03-24 15:14 millert + + * configure.in, configure: OSF/1 puts file formats in section 4, + not 5. + +2000-03-24 15:13 millert + + * CHANGES, INSTALL, sudo.c: Make login class support work on BSD/OS + +2000-03-23 20:24 millert + + * RUNSON: Update for 1.6.3 + +2000-03-23 20:23 millert + + * configure, configure.in: If there is no inet_addr but there *is* + an __inet_addr that's ok since inet_addr is probably just a macro + then. The better thing to do would be to look for the macro, but + this is fine for now. + +2000-03-23 19:50 millert + + * configure, configure.in: Don't use shlicc for BSD/OS 4.x + +2000-03-23 19:40 millert + + * Makefile.in, configure, configure.in: *.man lives in cwd, *.cat + lives in $(srcdir), add a @mansrcdir@ configure variable so we + can deal with this. Also, only remove *.man for 'distclean' not + 'clean'. + +2000-03-23 19:16 millert + + * sudo.c: set_loginclass() should be static like the proto says + +2000-03-23 14:14 millert + + * fnmatch.c: Add #ifdef __STDC__ around the rangematch function + header to avoid promotion of test to int, thus violating the + prototype. Gcc handles this gracefully but more std ANSI + compilers will complain. + +2000-03-23 10:11 millert + + * emul/fnmatch.h: Pull in newer fnmatch(3) that supports + FNM_CASEFOLD + +2000-03-23 10:11 millert + + * aclocal.m4, configure, fnmatch.3, fnmatch.c: Pull in newer + fnmatch(3) that supports FNM_CASEFOLD Check for FNM_CASEFOLD in + configure + +2000-03-22 23:41 millert + + * CHANGES, TODO: update for 1.6.3 + +2000-03-22 23:38 millert + + * lex.yy.c, parse.c, parse.h, parse.lex, parse.yacc, sudo.tab.h, + testsudoers.c, visudo.c: Fully qualified hosts w/ wildcards were + not matching the FQHOST token type. There's really no need for a + separate token for fully-qualified vs. unqualified anymore so + FQHOST is now history and hostname_matches now decides which + hostname (short or long) to check based on whether or not the + pattern contains a '.'. + +2000-03-22 23:09 millert + + * parse.c, parse.h, parse.yacc, sudoers.pod, testsudoers.c, + visudo.c, sudoers.cat, sudoers.man.in: Add support for wildcards + in the hostname. + +2000-03-22 22:50 millert + + * Makefile.in: Add targets for *.man.in, using config.status to + generate *.man from *.man.in + +2000-03-22 22:20 millert + + * sudoers.cat, sudoers.man.in, sudoers.pod: Document set_logname + option and enbolden refs to sudo and visudo. + +2000-03-22 19:35 millert + + * INSTALL, Makefile.in, aclocal.m4, configure, configure.in, + sudo.cat, sudo.pod, sudo.man.in, sudoers.cat, sudoers.pod, + visudo.cat, visudo.pod, sudoers.man.in, visudo.man.in: Add + FreeBSD login.conf support (untested on BSD/OS) based on a patch + from Michael D. Marchionna. configure now does substitution on + the man pages, allowing us to fix up the paths and set the + section correctly. Based on an idea from Michael D. Marchionna. + +2000-03-22 19:27 millert + + * auth/passwd.c: Better fix for handling HP-UX aging info. + +2000-03-22 19:20 millert + + * sudo.c: Add support for set_logname run-time default + +2000-03-22 19:17 millert + + * sudo.man.in, sudoers.man.in, visudo.man.in: configure does + substitution on these to produce *.man + +2000-03-22 19:16 millert + + * sudo.man, sudoers.man, visudo.man: These files now get generated + from *.man.in at configure time. + +2000-03-22 18:40 millert + + * defaults.c, defaults.h: Add set_logname option so users can turn + off setting of LOGNAME/USER environment variables. + +2000-03-22 10:53 millert + + * testsudoers.c, lsearch.c, parse.c: kill register + +2000-03-13 15:52 millert + + * auth/passwd.c: HP-UX adds extra info at the end for password + aging so when comparing the result of crypt to pw_passwd we only + compare the first len(epass) bytes *unless* the user entered an + empty string for a password. + +2000-03-13 11:05 millert + + * logging.c: Get rid of grandchild hack, it was causing problems + and there is really no need for it. This fixes a bug where we + spin eating up CPU when the user runs a long-running process like + a shell. + +2000-03-07 14:26 millert + + * sudo.c: User can always specify a login class if he/she is + already root. + +2000-03-06 23:29 millert + + * config.h.in, configure, configure.in, defaults.c, defaults.h, + sudo.c, sudo.h: FreeBSD login class (login.conf) support. + +2000-03-06 14:42 millert + + * auth/sudo_auth.c: HAVE_SECUREWARE -> HAVE_GETPRPWNAM; fixes + secureware support + +2000-03-03 18:04 millert + + * auth/passwd.c: Truncate unencrypted password to 8 chars if + encrypted password is exactly 13 characters (indicateing standard + a DES password). Many versions of crypt() do this for you, but + not all (like HP-UX's). + +2000-03-01 21:01 millert + + * INSTALL, RUNSON: Mention that gcc on dynix may have problems + +2000-02-29 17:46 millert + + * Makefile.in: Link visudo with NET_LIBS since we now call syslog + via defaults.c + +2000-02-29 17:41 millert + + * defaults.c: Use Argv[0] as the first arg to openlog() since + visudo uses this too. + +2000-02-28 18:58 millert + + * sudo.c: Stash coredumpsize resource limit and retsore it before + the exec() Otherwise the child ends up with a coredumpsize of 0. + +2000-02-26 22:56 millert + + * sudo.cat, sudo.man, sudo.pod: document -S flag + +2000-02-26 22:54 millert + + * sudo.c: fix usage string + +2000-02-26 22:48 millert + + * CHANGES, RUNSON, TODO, sudo.c, sudo.h, tgetpass.c, + auth/aix_auth.c, auth/fwtk.c, auth/pam.c, auth/sudo_auth.c: Added + -S flag (read passwd from stdin) and tgetpass_flags global that + holds flags to be passed in to tgetpass(). Change echo_off param + to tgetpass() into a flags field. There are currently 2 possible + flags for tgetpass(): TGP_ECHO and TGP_STDIN. In tgetpass(), + abstract the echo set/clear via macros and if (flags & TGP_ECHO) + but echo is not set on the terminal, but sure to set it. + +2000-02-26 22:11 millert + + * tgetpass.c: Fixed a bug that caused an infinite loop when the + password timeout was disabled. + +2000-02-18 12:56 millert + + * CHANGES, defaults.c, defaults.h, getspwuid.c, sudo.c, sudo.h, + sudoers.cat, sudoers.man, sudoers.pod, visudo.c: Add rootpw, + runaspw, and targetpw options. + +2000-02-18 12:11 millert + + * CHANGES, defaults.c, sudoers.cat, sudoers.man, sudoers.pod, + visudo.c: enveditor -> env_editor + +2000-02-15 19:07 millert + + * BUGS, INSTALL, Makefile.in, README, configure, configure.in, + sudo.cat, sudo.man, sudoers.cat, sudoers.man, version.h, + visudo.cat, visudo.man: crank versino to 1.6.3 + +2000-02-15 19:03 millert + + * INSTALL, TODO, defaults.c, defaults.h, sudoers.cat, sudoers.man, + sudoers.pod, visudo.c: Add 'editor' and 'enveditor' sudoers + defaults and make visudo honor them. This means that visudo will + now parse the sudoers file *before* it is edited so a bogus + sudoers file will cause a warning to go to stderr. Also, visudo + checks the variables once--it does not check them after each + editor run since that could be confusing. + +2000-02-15 18:49 millert + + * RUNSON: 1.6.2 -> 1.6.2p1 + +2000-02-15 18:36 millert + + * check.c, sudo.c, sudo.h: Move user_is_exempt prototype into + sudo.h + +2000-02-13 13:38 millert + + * configure, configure.in: Fix thinko, some && should have been || + in the last commit + +2000-02-13 13:28 millert + + * configure, configure.in: Don't initialized Makefile variables to + be NULL since the user may want to import variables from their + environment. + +2000-02-03 21:09 millert + + * configure, configure.in: typo + +2000-01-27 15:01 millert + + * INSTALL, RUNSON, configure, configure.in: Make pam work on HP-UX + 11.0;jaearick@colby.edu + +2000-01-27 15:01 millert + + * CHANGES: recent changes; prepare for 1.6.2p1 + +2000-01-26 23:31 millert + + * find_path.c: Don't apply SECURE_PATH if user is example; + jmknoble@pobox.com + +2000-01-26 16:21 millert + + * sudoers.cat, sudoers.man, sudoers.pod: Expanded docs on sudoers + 'defaults' options based on INSTALL file info. + +2000-01-26 16:21 millert + + * INSTALL: Fix some while lies + +2000-01-24 10:48 millert + + * Makefile.in: When making a bindist, link FAQ to TROUBLESHOOTING + instead of copying. + +2000-01-23 22:57 millert + + * sudoers.cat, sudoers.man, sudoers.pod: Add netgroup caveat + +2000-01-23 22:42 millert + + * RUNSON: Last minute updates + +2000-01-23 22:26 millert + + * TROUBLESHOOTING: PAM entry + +2000-01-23 22:23 millert + + * auth/pam.c: correct a comment + +2000-01-23 22:03 millert + + * CHANGES, RUNSON: update for 1.6.2 + +2000-01-23 21:59 millert + + * auth/pam.c: Better detection of PAM errors and fix custom prompts + with PAM. Based on patches from "Cloyce D. Spradling" + + +2000-01-20 11:15 millert + + * snprintf.c: Cast ULONG_MAX to unsigned long long when comparing + to an unsigned long long value. + +2000-01-19 14:07 millert + + * CHANGES, config.h.in, configure, configure.in, visudo.c: Fix + sudoers locking in visudo. We now lock the sudoers file itself, + not the temp file (since locking the temp file can foul up + editors). The previous locking scheme didn't work because the fd + was closed too early. + +2000-01-19 13:37 millert + + * configure, config.h.in, configure.in: Don't need test for + ftruncate() any more. + +2000-01-18 21:23 millert + + * configure, configure.in: Add a test for the -Aa flag w/ HP-UX's + cc. Fixes compilation with the unbundled HP-UX cc. + +2000-01-18 17:00 millert + + * sudoers.cat, sudoers.man, sudoers.pod: "a a" -> "a"; Aaron + Campbell + +2000-01-17 18:46 millert + + * LICENSE, Makefile.in, defaults.c, defaults.h, parse.c, parse.h, + parse.yacc, sudo.c, sudo.h, sudoers.pod, testsudoers.c, + tgetpass.c, version.h, visudo.c: update copyright year on changed + files + +2000-01-17 18:45 millert + + * RUNSON: updates + +2000-01-17 18:45 millert + + * CHANGES: aix fix + +2000-01-17 18:42 millert + + * INSTALL: Crank version to 1.6.2 + +2000-01-17 18:11 millert + + * configure: Crank version to 1.6.2 + +2000-01-17 17:46 millert + + * sudo.c: When using rlimit check for RLIM_INFINITY When computing + the value of maxfd, use min(getdtablesize(), RLIMIT_NOFILE) + +2000-01-17 12:32 millert + + * CHANGES: recent changes + +2000-01-17 12:28 millert + + * BUGS, Makefile.in, README, configure.in, sudo.cat, sudo.man, + sudoers.cat, sudoers.man, version.h, visudo.cat, visudo.man: + Crank version to 1.6.2 + +2000-01-17 12:25 millert + + * INSTALL, defaults.c, defaults.h, sudo.c, sudo.h, sudoers.pod: Add + 'shell_noargs' runtime option back in. We have to defer checking + until after the sudoers file has been parsed but since there are + now other options that operate that way this one can too. Based + on a patch from bguillory@email.com. + +2000-01-16 23:05 millert + + * defaults.c, defaults.h, parse.c, sudo.c, sudo.h: Add "listpw" and + "verifypw" options. + +2000-01-16 22:57 millert + + * sudoers.cat, sudoers.man, sudoers.pod: o Fix some typos/omissions + o Add section on verifypw and listpw o Define how NOPASSWD + interacts with the -v and -l flags + +2000-01-14 12:39 millert + + * configure, configure.in: For HP-UX cc, add -Aa to CPPFLAGS. For + HP-UX always add -D_HPUX_SOURCE to CPPFLAGS. + +2000-01-14 12:29 millert + + * defaults.c, defaults.h: In struct sudo_defs_types, move the union + to the end and don't initialize the union member since that only + works with an ANSI compiler. We set the value of the union by + hand in init_defaults() anyway. This allows sudo to compile on a + K&R compiler again. + +2000-01-11 13:20 millert + + * parse.c, parse.h, parse.yacc, testsudoers.c, visudo.c: + netgr_matches needs to check shost as well as host since they may + be different. + +2000-01-11 13:17 millert + + * tgetpass.c: End on \r as well as \n + +2000-01-02 23:53 millert + + * sudo.c: Update statbuf.st_mode based on SUDOERS_MODE when we are + chaning from 0400 to whatever SUDOERS_MODE is (converting from + the old sudoers mode). Assumes that SUDOERS_MODE is less + restrictive than 0400 which should always be the case. + +2000-01-02 23:43 millert + + * parse.c, parse.yacc, sudo.c, sudo.h: Make treatment of -l and -v + sane wrt NOPASSWD flags. Now allow -l w/o a passwd if there is + *any* entry for the user on the host with a NOPASSWD flag. For + -v, only allow w/o a passwd if *all* entries for the user on the + host w/ the specified runas user have the NOPASSWD flag set. + +2000-01-02 23:26 millert + + * Makefile.in: add check target + +1999-12-16 13:02 millert + + * visudo.c: Treat EOF at whatnow prompt like 'x' instead of + looping. + +1999-12-10 00:09 millert + + * CHANGES: recent changes + +1999-12-08 23:04 millert + + * config.h.in, configure, configure.in, sudo.c: Add check for + initgroups() since old SYSV lacks this. + +1999-12-08 22:54 millert + + * CHANGES, RUNSON, aclocal.m4, config.h.in, configure, + configure.in, parse.c, testsudoers.c: o Kill HAVE_FNMATCH_H o + Only define HAVE_FNMATCH if exists. + +1999-12-06 01:47 millert + + * CHANGES, RUNSON, insults.h, auth/sudo_auth.c: Don't allow insults + to be enabled if the insults[] array is empty. Otherwise there + would be division by zero. + +1999-12-06 01:25 millert + + * insults.h: Don't care about USE_INSULTS #define since the insult + stuff may be overridden at runtime. + +1999-12-06 01:23 millert + + * auth/sudo_auth.c: Honor insults flag. + +1999-12-05 19:14 millert + + * CHANGES, parse.c: Don't ask the user for a password if the user + is not allowed to run the command and the authenticate flag (in + sudoers) is false. + +1999-12-05 19:05 millert + + * CHANGES, RUNSON, lex.yy.c, parse.lex: o Whenever we get a bare + newline we change to the INITIAL state. o Enter GOTRUNAS when we + see Runas_Alias + + This allows #uid to work in a RunasAlias. + +1999-12-05 14:06 millert + + * CHANGES, parse.yacc: fix parsing of runas lists: o oprunasuser + and runaslist now return a value o in a runasspec, if a runaslist + does not return TRUE, set runas_matches to FALSE. Normally, a + runaslist only returns FALSE for explicitly denied users. o + since runaslist does not modify the stack there is no need for a + push/pop in runasalias. + +1999-12-04 21:54 millert + + * check.c, sudo.c: Don't kill the user's tickets until after + sudoers has been parsed since tty_tickets and ticket_dir could be + set in sudoers. + +1999-12-04 21:18 millert + + * BUGS, CHANGES, Makefile.binary, Makefile.in, README, RUNSON, + configure, configure.in, sudo.cat, sudo.man, sudoers.cat, + sudoers.man, tgetpass.c, version.h, visudo.cat, visudo.man: crank + version to 1.6 + +1999-12-04 21:18 millert + + * testsudoers.c: add set_fqdn() stub + +1999-12-02 15:31 millert + + * INSTALL, defaults.c, defaults.h, sudo.c, sudo.h, sudoers.cat, + sudoers.man, sudoers.pod, visudo.c: o Kill shell_noargs option, + it cannot work since the command needs to be set before sudoers + is parsed. o Fix the "set_home" sudoers option (only worked at + compile time). o Fix "fqdn" sudoers option. We now set + host/shost via set_fqdn which gets called when the "fqdn" + option is set in sudoers. o Move the openlog() to + store_syslogfac() so this gets overridden correctly from the + sudoers file. + +1999-12-02 15:21 millert + + * auth/securid.c: SecurID support should compile now. + +1999-11-28 20:56 millert + + * sudo.pod, visudo.pod, sudo.cat, sudo.man, sudoers.man, + visudo.man, sudoers.cat, visudo.cat: fix some syntactic goofs + +1999-11-28 18:51 millert + + * sudo.html, sudoers.html, Makefile.in, visudo.html: No longer need + the .html files as they are generated automatically on the web + site. + +1999-11-28 18:49 millert + + * CHANGES, LICENSE: kill characters that made wml unhappy + +1999-11-28 18:34 millert + + * HISTORY: typo + +1999-11-25 12:05 millert + + * README: majordomo@cs.colorado.edu -> majordomo@courtesan.com + +1999-11-24 19:43 millert + + * Makefile.in, configure: Wrap script execution w/ /bin/sh for the + benefit of ctm + +1999-11-23 22:52 millert + + * sudo.c: Make the -s flag be exclusive too. Also reorder the + flags in the exclusive usage message so they are alphabetical. + +1999-11-23 13:27 millert + + * auth/pam.c: make pam errors other than PAM_PERM_DENIED fatal + +1999-11-23 13:07 millert + + * auth/API: fix typo + +1999-11-23 13:07 millert + + * INSTALL: make it clear that /etc/pam.d/sudo is required on linux + +1999-11-23 13:06 millert + + * auth/pam.c: fix a warning on redhat and spew an error if + pam_authenticate() returns an error other than AUTH_SUCCESS or + PAM_PERM_DENIED + +1999-11-23 00:43 millert + + * sudo.cat, sudo.html, sudo.man, sudo.pod: Be very clear that the + password required is the user's not root's + +1999-11-19 21:04 millert + + * Makefile.in: add sample.syslog.conf to DISTFILES and BINFILES + +1999-11-18 19:13 millert + + * RUNSON: updates from Brian Jackson + some formatting + +1999-11-17 21:39 millert + + * INSTALL.binary, Makefile.binary, README, RUNSON: o One RUNSon + update o Changes for automating real binary releases + +1999-11-17 21:38 millert + + * Makefile.in: Add bindist target + +1999-11-16 16:26 millert + + * TROUBLESHOOTING: talk about run-time options in addition to + compile-time options + +1999-11-16 01:16 millert + + * CHANGES: fix typos + +1999-11-16 01:09 millert + + * sudo.c: need sys/time.h if HAVE_SETRLIMIT + +1999-11-16 00:42 millert + + * PORTING, README, RUNSON, sudo.c, sudo.cat, sudo.html, sudo.man, + sudo.pod, visudo.cat, visudo.html, visudo.man, visudo.pod: get + rid of references to sudo-bugs. Now mention the web site or the + sudo@ alias + +1999-11-16 00:35 millert + + * sudoers.html: repair pod2html damage + +1999-11-16 00:28 millert + + * RUNSON, TODO: Update for 1.6 release + +1999-11-16 00:23 millert + + * sudoers.cat, sudoers.html, sudoers.man, sudoers.pod: Add warning + about using ALL in a command context. + +1999-11-09 15:12 millert + + * visudo.c: Call yyrestart() on a parse error to reset the lexer + state. + +1999-11-09 15:06 millert + + * parse.lex, lex.yy.c: Don't need YY_FLUSH_BUFFER after all Move + yyrestart() into visudo.c since it might not get called in yywrap + if we get a parse error (and we only reread the file on error + anyway). + +1999-11-09 14:32 millert + + * parse.lex, lex.yy.c: Call YY_FLUSH_BUFFER macro in yywrap() to + clean up any buffers that might still exist. Call yyrestart() + instead of using the deprecated YY_NEW_FILE macro. + +1999-11-09 12:13 millert + + * lex.yy.c, parse.lex: flex doesn't need %N table size declarations + +1999-11-08 19:00 millert + + * sudoers.cat, sudoers.html, sudoers.man, sudoers.pod: Mention what + characters need to be escaped in names. + +1999-11-08 18:59 millert + + * configure: regen + +1999-11-08 18:59 millert + + * INSTALL: clarify Mac OS X entry + +1999-11-08 18:59 millert + + * RUNSON: update + +1999-11-08 17:45 millert + + * configure.in: o Use AC_MSG_ERROR throughout o Check syslog + configure options for danity + +1999-11-05 17:11 millert + + * defaults.c: Fix printing of type T_MODE in dump_defaults() + +1999-11-05 12:00 millert + + * strcasecmp.c: missing sys/types.h + +1999-11-05 00:42 millert + + * INSTALL: Break out options that may be overridden at run time + into their own section. Add a not about Max OS X and correct + some lies. + +1999-11-04 14:01 millert + + * CHANGES, config.h.in, configure, configure.in, sudo.c: o Now use + getrlimit to find the highest fd when closing all non-std fd's o + Turn off core dumps via setrlimit for the sake of paranoia + +1999-11-04 13:57 millert + + * RUNSON: updates + +1999-11-01 10:59 millert + + * CHANGES: updates + +1999-11-01 10:58 millert + + * tgetpass.c: When read()'ing, do a single character at a time to + be sure we don't go oast the newline. + +1999-11-01 10:43 millert + + * sudo.c: For the sudo_root option, check against user_uid, not + getuid() since at this point, ruid == euid == 0. + +1999-10-31 23:14 millert + + * RUNSON: some updates + +1999-10-31 23:14 millert + + * logging.h: Fix compilation problem when --with-logging=file was + specified. This means that syslog is now required to build sudo + but that should not be a problem. If it is it can be fixed + trivially with a configure check for syslog() or syslog.h. + +1999-10-31 23:00 millert + + * tgetpass.c: Make this work again for things like "sudo echo hi | + more" where the tty gets put into character at a time mode. We + read until we read end of line or we run out of space (similar to + fgets(3)). + +1999-10-20 11:23 millert + + * sudoers.cat, sudoers.html, sudoers.man, sudoers.pod: change ital + to bold + +1999-10-20 11:23 millert + + * RUNSON: update + +1999-10-16 13:56 millert + + * defaults.c: Error out if syslog parameters are given without a + value. For Ultrix or 4.2BSD "syslog" is allowed without a value + since there are no facilities in the 4.2BSD syslog. + +1999-10-15 16:37 millert + + * defaults.c: Ignore the syslog facility for systems w/ old syslog + like Ultrix. + +1999-10-15 12:51 millert + + * TROUBLESHOOTING: people with "." early in their path can have + problems running sudo from the build dir ;-) + +1999-10-13 00:18 millert + + * sudo.man, sudo.pod, sudo.cat, sudo.html: Remove -r realm option + +1999-10-12 22:34 millert + + * configure, configure.in, sudo.c, auth/kerb5.c, auth/sudo_auth.c, + auth/sudo_auth.h: New krb5 code from Frank Cusack + . + +1999-10-12 22:33 millert + + * CHANGES: update to reality + +1999-10-11 20:53 millert + + * auth/fwtk.c: include to get function prototypes. + +1999-10-11 20:05 millert + + * sudo.cat, sudo.html, sudo.man, sudo.pod: document -L flag + +1999-10-11 19:42 millert + + * sudo.c: in set_perms(), always call setuid(0) before changing the + ruid/euid so we always know it will succeed. + +1999-10-11 12:24 millert + + * defaults.h: #undef T_FOO to avoid conflicts with system defines + (like on ULTRIX). + +1999-10-11 11:55 millert + + * TODO, sample.sudoers, sudoers.cat, sudoers.html, sudoers.man, + sudoers.pod: Docuement "Defaults" lines in /etc/sudoers. Still + needs some fleshing out but this is a start. + +1999-10-10 17:21 millert + + * defaults.c: use strtol, not strtoul since not everyone has not + strtoul + +1999-10-10 15:01 millert + + * lex.yy.c, parse.lex: last {WORD} rule should only apply in the + INITIAL state + +1999-10-10 14:38 millert + + * lex.yy.c, parse.lex: o Add support for escaped characters in the + WORD macro o Modify fill() to squash escape chars + +1999-10-10 13:56 millert + + * defaults.c, defaults.h: o Add T_PATH flag to allow simple sanity + checks for default values that are supposed to be pathnames. o + Fix a duplicate free when visudo finds an error. + +1999-10-09 01:01 millert + + * defaults.c, defaults.h, logging.c: mail_if_foo -> mail_foo + +1999-10-07 21:12 millert + + * compat.h, defaults.c, defaults.h, sudo.c, tgetpass.c: o Add + requiretty option o Move O_NOCTTY to compat.h + +1999-10-07 21:12 millert + + * logging.c: The exit() in log_error() was mistakenly removed in a + previous version. Put it back... + +1999-10-07 17:20 millert + + * INSTALL, TODO, check.c, config.h.in, configure, configure.in, + defaults.c, defaults.h, find_path.c, getspwuid.c, lex.yy.c, + logging.c, parse.yacc, sudo.c, auth/aix_auth.c, auth/fwtk.c, + auth/pam.c, auth/rfc1938.c, auth/sia.c, auth/sudo_auth.c: o + Change defaults stuff to put the value right in the struct. o + Implement mailer_flags o Store syslog stuff both in int and + string form. Setting the string form magically updates the int + version. o Add boolean attribute to strings where it makes sense + to say !foo + +1999-10-07 17:13 millert + + * tgetpass.c: add O_NOCTTY when opening /dev/tty just in case + +1999-10-06 00:48 millert + + * auth/API: cleanup function no longer takes a status arg + +1999-10-06 00:48 millert + + * INSTALL: the the + +1999-09-15 05:15 millert + + * TODO, config.h.in, configure, configure.in, logging.c: Use + strftime() instead of ctime() if it is available. + +1999-09-14 12:58 millert + + * defaults.c: fix copyright date + +1999-09-14 12:57 millert + + * RUNSON: update ReliantUNIX entry + +1999-09-14 12:56 millert + + * defaults.c, defaults.h, logging.c: add log_year option + +1999-09-14 04:01 millert + + * configure, configure.in: add --without-sendmail to help output + +1999-09-14 03:42 millert + + * configure, configure.in: enforce an otctal arg for + --with-suoders-mode + +1999-09-08 04:06 millert + + * BUGS, INSTALL, Makefile.in, TODO, aclocal.m4, check.c, + config.h.in, configure, configure.in, defaults.c, defaults.h, + find_path.c, lex.yy.c, logging.c, parse.h, parse.lex, parse.yacc, + sudo.c, sudo.h, sudo.tab.h, testsudoers.c, version.c, visudo.c, + auth/aix_auth.c, auth/fwtk.c, auth/kerb5.c, auth/pam.c, + auth/rfc1938.c, auth/sia.c, auth/sudo_auth.c: Add support for + "Defaults" line in sudoers to make configuration variables + changable at runtime (and on a global, per-host and per-user + basis). Both the names and the internal representation are still + subject to change. It was necessary to make sudo_user.runas but + a char ** instead of a char * since this value can be changed by + a Defaults line. There is a similar (but more complicated) issue + with sudo_user.prompt but it is handled differently at the + moment. + + Add a "-L" flag to list the name of options with their + descriptions. This may only be temporary. + + Move some prototypes to parse.h + + Be much less restrictive on what is allowed for a username. + +1999-09-08 04:01 millert + + * sample.syslog.conf: Add more info + +1999-09-04 03:09 millert + + * fnmatch.3, fnmatch.c, getcwd.c, lsearch.c, snprintf.c, + strcasecmp.c, LICENSE: UCB has dropped the advertising clause + from their license. + +1999-08-31 05:39 millert + + * auth/sudo_auth.h: move dce_verofy proto to correct section + +1999-08-31 05:39 millert + + * auth/dce.c: remove XXX + +1999-08-28 06:00 millert + + * emul/fnmatch.h: Add fnmatch() prototype + +1999-08-28 06:00 millert + + * fnmatch.c, parse.c, testsudoers.c: Move inclusion of + emul/fnmatch.h to be after sudo.h for __P + +1999-08-28 05:59 millert + + * sudo.h: add strcasecmp proto + +1999-08-28 05:50 millert + + * auth/sudo_auth.c: add check for case where there are no auth + methods + +1999-08-28 05:36 millert + + * configure, configure.in: Define _XOPEN_EXTENDED_SOURCE on AIX and + __USE_FIXED_PROTOTYPES__ on SunOS4 w/ gcc + +1999-08-28 05:24 millert + + * getspwuid.c, lex.yy.c, parse.lex, parse.yacc: include strings.h + everywhere we include string.h + +1999-08-28 05:22 millert + + * version.c: nicer output when showing auth methods + +1999-08-28 05:00 millert + + * version.c: Add support for SEND_MAIL_WHEN_NO_HOST + +1999-08-28 04:49 millert + + * config.h.in, configure.in, configure: Add _GNU_SOURCE for Linux + +1999-08-28 04:22 millert + + * parse.lex, lex.yy.c: fix definition of OCTECT + +1999-08-28 04:10 millert + + * configure, configure.in: aix_auth.o not authenticate.o + +1999-08-27 17:02 millert + + * sudo.c: Only block SIGINT, SIGQUIT, SIGTSTP (which can be + generated from the keyboard). Since we run with ruid/euid == 0 + the user can't really signal us in nasty ways. + +1999-08-27 17:01 millert + + * visudo.c: Don't need to worry about catching too many signals + since we do locking on the tmp file. If a lockfile is really + stale, it will be detected and overwritten. + +1999-08-27 16:09 millert + + * INSTALL, Makefile.in: include auth/API in tarball + +1999-08-27 16:09 millert + + * auth/sudo_auth.c: move memset() of plaintext pw outside of verify + loop and only do the memset if we are *not* in standalone mode. + +1999-08-27 13:46 millert + + * auth/: sudo_auth.c, sudo_auth.h: DCE is not a standalone method + +1999-08-27 11:53 millert + + * sudo.c: fix --enable-noargs-shell + +1999-08-27 11:06 millert + + * snprintf.c: "#ifdef __STDC__" not "#if __STDC__" (I missed one) + +1999-08-27 10:54 millert + + * auth/: fwtk.c, sia.c: _cleanup() function returns an int. + +1999-08-27 10:50 millert + + * auth/dce.c: there were still some return(0)'s hanging around, + make them AUTH_FAILURE + +1999-08-27 10:39 millert + + * parse.c: typo in comment + +1999-08-27 10:03 millert + + * version.c: add missing semicolon + +1999-08-27 08:31 millert + + * auth/sudo_auth.h: missing backslash + +1999-08-26 17:24 millert + + * CHANGES, config.h.in, configure, configure.in: Kill + _XOPEN_EXTENDED_SOURCE -- causes problems on some OSes + +1999-08-26 09:21 millert + + * Makefile.in: add parse.h to HDRS + +1999-08-26 09:16 millert + + * Makefile.in, configure, configure.in: Kill VISUDO_LIBS and + VISUDO_LDFLAGS. Add LIBS, NET_LIBS, and LDFLAGS. Common libs go + in LIBS, commong ld flags go in LDFLAGS and network libs like + -lsocket, -lnsl go in NET_LIBS. This allows testsudoers to build + on Solaris and is a bit cleaner in general. + +1999-08-26 06:56 millert + + * UPGRADE: mention ptmp -> sudoers.tmp + +1999-08-26 06:12 millert + + * configure.in, configure, config.h.in: Define + _XOPEN_SOURCE_EXTENDED not _XOPEN_SOURCE + +1999-08-26 05:37 millert + + * RUNSON: add 2 reports + +1999-08-26 05:20 millert + + * auth/kerb5.c: Minor changes, mostly cosmetic. + verify_krb_v5_tgt() changed to return a value more like a system + function + +1999-08-26 05:19 millert + + * auth/dce.c: Add an XXX + +1999-08-26 05:19 millert + + * TODO: more things todo! + +1999-08-26 05:18 millert + + * sample.sudoers: update based on what is in the man page + +1999-08-26 05:10 millert + + * parse.yacc: minor change to first line printed in -l mode + +1999-08-26 05:10 millert + + * sudo.cat, sudo.html, sudo.man, sudo.pod: rename "ENVIRONMENT + VARIABLES" section to "ENVIRONMENT" to be more standard and add + "EXAMPLES" section + +1999-08-26 05:08 millert + + * visudo.cat, visudo.html, visudo.man, visudo.pod: rename + "ENVIRONMENT VARIABLES" section to "ENVIRONMENT" to be more + standard + +1999-08-26 05:06 millert + + * logging.c, parse.c, sudo.h: add FLAG_NO_CHECK + +1999-08-26 05:05 millert + + * parse.lex, lex.yy.c: make an OCTET really be limited to 0-255 + +1999-08-26 05:04 millert + + * UPGRADE: mention timestamp changes + +1999-08-26 05:04 millert + + * PORTING: cosmetic cleanup + +1999-08-26 05:00 millert + + * sudoers.cat, sudoers.html, sudoers.man, sudoers.pod: new + sudoers(8) man page + +1999-08-24 13:45 millert + + * version.c: Update comments about syslog name tables + +1999-08-24 13:37 millert + + * CHANGES, LICENSE, Makefile.in, configure, strcasecmp.c, + configure.in, parse.yacc: include strcasecmp() for those without + it + +1999-08-24 12:43 millert + + * sample.sudoers: Use the : operator some more and fix a typo + +1999-08-24 12:43 millert + + * HISTORY: update the history of sudo + +1999-08-24 12:42 millert + + * parse.c, parse.lex, testsudoers.c: CIDR-style netmask support + +1999-08-24 12:41 millert + + * CHANGES: recent changes + +1999-08-24 12:40 millert + + * sudo.tab.h: these should be generated with byacc, not bison + +1999-08-24 12:40 millert + + * lex.yy.c: regen + +1999-08-24 11:58 millert + + * parse.h, parse.yacc, sudo.tab.h: In "sudo -l" mode, the type of + the stored (expanded) alias was not stored with the contents. + This could lead to incorrect output if the sudoers file had + different alias types with the same name. Normal parsing (ie: + not in '-l' mode) is unaffected. + +1999-08-23 12:47 millert + + * configure, configure.in: define _XOPEN_SOURCE to get at crypt() + proto on some systems + +1999-08-22 13:10 millert + + * snprintf.c: fix comment + +1999-08-22 13:09 millert + + * tgetpass.c: don't need limits.h + +1999-08-22 07:36 millert + + * snprintf.c: kill bogus reference to vfprintf + +1999-08-22 07:26 millert + + * sample.sudoers, sudoers: better examples + +1999-08-22 07:23 millert + + * snprintf.c: Add some const in the K&R defs. This is safe since + we define const away if the compiler doesn't grok it. + +1999-08-22 07:22 millert + + * aclocal.m4, configure: Better test for working long long support. + Ultrix compiler supports basic long long but not all operations + on them. + +1999-08-22 05:59 millert + + * aclocal.m4, config.h.in, configure, getspwuid.c, snprintf.c, + sudo.c, auth/secureware.c: Add check for LONG_IS_QUAD #undef + MAXINT before including hpsecurity.h to silence an HP-UX warning + Check for U?LONG_LONG_MAX in snprintf.c and use LONG_IS_QUAD + +1999-08-21 15:00 millert + + * LICENSE, aclocal.m4, config.h.in, configure, configure.in, + snprintf.c: UCB-derived snprintf + asprintf support. Supports + quads if the compiler does. No floating point yet, perhaps + later... + +1999-08-20 16:37 millert + + * check.c, find_path.c, goodpath.c, logging.c, parse.c, sudo.c, + auth/API, auth/sudo_auth.c, auth/sudo_auth.h: Run most of the + code as root, not the invoking user. It doesn't really gain us + anything to run as the user since an attacker can just have an + setuid(0) in their egg. Running as root solves potential + problems wrt signalling. + +1999-08-19 13:45 millert + + * logging.c, sudo.c: Don't wait for child to finish in log_error(), + let the signal handler get it if we are still running, else let + init reap it for us. The extra time it takes to wait lets the + user know that mail is being sent. + + Install SIGCHLD handler in main() and for POSIX signals, block + everything *except* SIGCHLD. + +1999-08-19 12:30 millert + + * logging.c, parse.c, parse.yacc, sudo.c, configure, sudo.h, + INSTALL, config.h.in, configure.in: sudoers_lookup() now returns + a bitmap instead of an int. This makes it possible to express + things like "failed to validate because user not listed for this + host". Some thigns that were previously VALIDATE_FOO are now + FLAG_FOO. This may change later on. + + Reorganized code in log_auth() and sudo.c to deal with above + changes. + + Safer versions of push/pushcp with in the do { ... } while (0) + style + + parse.yacc now saves info on the stack to allow parse.c to + determine if a user was listed, but not for the host he/she tried + to run on. + + Added --with-mail-if-no-host option + +1999-08-17 11:29 millert + + * parse.yacc, sudo.h, visudo.c, visudo.cat, visudo.html, + visudo.man, visudo.pod: o NewArgv and NewArgc don't need to be + externally visible. o If pedantic > 1, it is a parse error. o + Add -s (strict) option to visudo which sets pedantic to 2. + +1999-08-17 11:26 millert + + * HISTORY, INSTALL: Just have sudo-bugs contact info in one place + +1999-08-17 11:20 millert + + * sudo.cat, sudo.html, sudo.man, sudo.pod: Add BUGS section + +1999-08-17 10:29 millert + + * configure, configure.in, Makefile.in: Add testsudoers to default + build target if --with-devel Don't clean generated parser files + unless "distclean". + +1999-08-17 08:47 millert + + * parse.yacc: In pedantic mode we need to save *all* the aliases, + not just those that match, or we get spurious warnings. + +1999-08-17 05:32 millert + + * TROUBLESHOOTING: reference samples.sylog.conf + +1999-08-14 11:50 millert + + * sample.syslog.conf: Sample entries for syslog.conf + +1999-08-14 11:40 millert + + * CHANGES: recent changes + +1999-08-14 11:36 millert + + * auth/: API, afs.c, aix_auth.c, dce.c, fwtk.c, kerb4.c, kerb5.c, + pam.c, passwd.c, rfc1938.c, secureware.c, securid.c, sia.c, + sudo_auth.c, sudo_auth.h: In struct sudo_auth, turn need_root and + configured into flags and add a flag to specify an auth method is + running alone (the only one). Pass auth methods their sudo_auth + pointer, not the data pointer. This allows us to get at the + flags and tell if we are the only auth method. That, in turn, + allows the method to be able to decide what should/should not be + a fatal error. Currently only rfc1938 uses it this way, which + allows us to kill the OTP_ONLY define and te hackery that went + with it. With access to the sudo_auth struct, methods can also + get at a string holding their cannonical name (useful in error + messages). + +1999-08-14 11:34 millert + + * Makefile.in, INSTALL, README, config.h.in, configure, + configure.in, getspwuid.c, lex.yy.c, parse.lex, parse.yacc, + sudo.tab.h: o --with-otp deprecated, use --without-passwd instead + o real dependencies in the Makefile o --with-devel option to + enable yacc, lex, and -Wall o style -- "foo -> bar" becomes + "foo->bar" o ALL goes back to being a token, not a string but + don't leak memory o rename hsotspec -> host in parse.yacc + +1999-08-12 12:26 millert + + * BUGS, CHANGES: recent changes + +1999-08-12 12:24 millert + + * configure, configure.in, interfaces.c, snprintf.c, sudo.c, + sudo.h, auth/sudo_auth.c: o Digital UNIX needs to check for + *snprintf() before -ldb is added to LIBS since -ldb includes a + bogus snprintf(). o Add forward refs for struct mbuf and struct + rtentry for Digital UNIX. o Reorder some functions in snprintf.c + to fix -Wall o Add missing includes to fix more -Wall + +1999-08-12 10:37 millert + + * INSTALL, check.c, config.h.in, configure, configure.in, + parse.yacc, testsudoers.c, version.c, visudo.c, auth/sudo_auth.c: + o Add a "pedentic" flag to the parser. This makes sudo warn in + cases where an alias may be used before it is defined. Only + turned on for visudo and testsudoers. o Add + --disable-authentication option that makes sudo not require + authentication by default. The PASSWD tag can be used to require + authentication for an entry. We no longer overload + --without-passwd. + +1999-08-12 10:29 millert + + * lex.yy.c, parse.lex: Break 'WORD' regexp def into HOSTNAME and + USERNAME. These days a username can contain just about anything + so be very permissive. Also drop the unused \. punctuation. + +1999-08-09 18:25 millert + + * parse.yacc: o add a 'val' element to aliasinfo struct and move -> + parse.h o find_alias() now returns an aliasinfo * instead of + boolean o add_alias() now takes a value parameter to store in the + aliasinfo.val o The cmnd, hostspec, runasuser, and user rules now + return: 1) positive match 0) negative match (due to '!') -1) no + match This means setting $$ explicitly in all cases, which I + should have done in the first place. It also means that we + always store a value that is != -1 and when we see a '!' we can + set *_matches to !rv if rv != -1. The upshot of all of this is + that '!' now works the way it should in lists and some of the + rules are more uniform and sensible. + +1999-08-09 18:17 millert + + * Makefile.in: add parse.h dependency + +1999-08-09 18:17 millert + + * parse.h: kill unused *_matched macros + +1999-08-09 10:35 millert + + * parse.yacc: Allow a list of users as the first thing in a user + spec, not just a single entry. This makes things more uniform, + though it does allow you to write user specs that are hard to + read. + +1999-08-09 10:08 millert + + * configure: regen + +1999-08-09 10:08 millert + + * configure.in: fix check for crypt() in libufc + +1999-08-07 14:03 millert + + * README: sudo-users list now exists + +1999-08-07 07:46 millert + + * INSTALL, PORTING, README, TODO, TROUBLESHOOTING: Update to + reality. + +1999-08-07 05:59 millert + + * CHANGES, Makefile.in, TODO, TROUBLESHOOTING, check.c, compat.h, + config.h.in, configure.in, logging.c, sudo.h, version.c, + visudo.c, configure, fileops.c: o Move lock_file() and touch() + into fileops.c so visudo can use them o Visudo now locks the + sudoers temp file instead of bailing when the temp file already + exists. This fixes the problem of stale temp files but it does + *require* that you not try to put the temp file in a + world-writable directory. This shoud not be an issue as the temp + file should live in the same dir as sudoers. o Visudo now only + installs the temp file as sudoers if it changed. + +1999-08-06 09:49 millert + + * logging.c: add fcntl locking + +1999-08-06 09:33 millert + + * configure, config.h.in, configure.in, logging.c: Lock the log + file. + +1999-08-06 05:36 millert + + * Makefile.in, TROUBLESHOOTING, parse.c, pathnames.h.in, sudo.c, + visudo.c, visudo.cat, visudo.html, visudo.man, visudo.pod: o + /etc/stmp -> /etc/sudoers.tmp since solaris uses stmp as shadow + temp file o _PATH_SUDO_SUDOERS -> _PATH_SUDOERS and + _PATH_SUDO_STMP -> _PATH_SUDOERS_TMP + +1999-08-05 17:38 millert + + * INSTALL, check.c, config.h.in, configure, configure.in, + version.c: o Kill *_MESSAGE and replace with NO_LECTURE o Add + more things to root sudo -V config reporting + +1999-08-05 10:56 millert + + * configure, configure.in: aix_auth.o not authenticate.o + +1999-08-05 10:48 millert + + * config.h.in: Add --with-goodpri and --with-badpri configure + options to specify the syslog priority to use. + +1999-08-05 10:30 millert + + * INSTALL, configure.in, logging.h, configure: Add --with-goodpri + and --with-badpri configure options to specify the syslog + priority to use. + +1999-08-05 10:25 millert + + * compat.h: kill crufty AIX stuff + +1999-08-05 06:55 millert + + * Makefile.in: Sigh, some versions of make (like Solaris's) don't + deal with $< like I would expect. Both GNU and BSD makes get + this right but... So, we just expand $< inline at the cost of + some ugliness. + +1999-08-05 06:52 millert + + * version.c: If the invoking user is root, sudo will now print + configure info in -V mode. Currently just prints logging info, + to be expanded later. + +1999-08-05 06:51 millert + + * logging.c, logging.h, sudo.c, sudo.h: o new defines for syslog + facility and priority o use new print_version() functino for -V + mode + +1999-08-05 06:49 millert + + * check.c: Don't need version.c + +1999-08-05 06:21 millert + + * configure, configure.in, aclocal.m4, config.h.in: Add check for + syslog facilities and priorities tables in syslog.h + +1999-08-05 05:23 millert + + * Makefile.in: o authenticate -> aix_auth o add version.c + +1999-08-05 05:21 millert + + * auth/sudo_auth.c: Missed a prompt -> user_prompt conversion + +1999-08-04 13:32 millert + + * TODO: sudo should lock its logfile + +1999-08-04 13:28 millert + + * parse.yacc: o Add '!' correctly when expanding Aliases. o Add + shortcut macros for append() to make things more readable. o The + separator in append() is now a string instead of a char. o In + append(), only prepend the separator if the last char is not a + '!'. This is a hack but it greatly simplifies '!' handling. o + In -l mode, Runas lists and NOPASSWD/PASSWD tags are now + inherited across entries in a list (matches current behavior). + o Fix formatting in -l mode such that items in a list are + separated by a space. Greatlt improves readability. o Space + for name field in struct aliasinfo is now allocated dyanically + instead of using a (big) buffer. o In add_alias(), only search + the list once (lsearch instead of lfind + lsearch) + +1999-08-04 11:31 millert + + * lex.yy.c, sudo.tab.h: regen + +1999-08-04 10:54 millert + + * configure, configure.in: Solais pam doesn't require anye xtra + setup + +1999-08-04 05:35 millert + + * parse.yacc: o Simpler '!' support now that the lexer deals with + multiple !'s for us. o In the case of opFOO, have FOO give a + boolean return value and set foo_matches in opFOO, not FOO. o + Treat 'ALL' as a string since it gets fill()'d in + parse.lex--fixes a small memory leak. In the long run it may + be better to just fix parse.lex and make ALL back into a token. + However, having it be a string is useful since it can be + easily passed back to the parent rule if we so desire. + +1999-08-04 03:54 millert + + * parse.lex: o Remove some unnecessary backslashes o collapse + multiple !'s by using !+ and checking if yyleng is even or odd. + this allows us to simplify ! handling in parse.yacc + +1999-08-04 03:53 millert + + * sudo.c: -u flag was being ignored + +1999-08-01 13:04 millert + + * Makefile.in: correct fix + +1999-08-01 12:37 millert + + * Makefile.in: work around pod2man stupididy + +1999-08-01 12:35 millert + + * Makefile.in: correct dependencies for .cat + +1999-08-01 12:26 millert + + * sudo.cat, sudo.man, visudo.cat, visudo.man: regen + +1999-08-01 12:25 millert + + * sudo.pod, visudo.pod: Add copyright Update to reality + +1999-08-01 11:42 millert + + * parse.c, sudo.c, sudo.h: rename validate() to the more + descriptive sudoers_lookup() + +1999-08-01 06:49 millert + + * auth/aix_auth.c: use tgetpass + +1999-07-31 12:32 millert + + * CHANGES: updates + +1999-07-31 12:31 millert + + * HISTORY, INSTALL, Makefile.in, README, RUNSON, TROUBLESHOOTING, + configure, configure.in, sudo.c: Sudo, not CU Sudo + +1999-07-31 12:19 millert + + * Makefile.in, alloc.c, check.c, compat.h, config.h.in, + find_path.c, getspwuid.c, goodpath.c, ins_2001.h, ins_classic.h, + ins_csops.h, ins_goons.h, insults.h, interfaces.c, interfaces.h, + lex.yy.c, logging.c, logging.h, parse.c, parse.h, parse.lex, + parse.yacc, pathnames.h.in, putenv.c, strerror.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, version.h, + visudo.c, auth/afs.c, auth/aix_auth.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/sia.c, + auth/sudo_auth.c, auth/sudo_auth.h, emul/search.h, emul/utime.h, + LICENSE: add 4th term to license similar to term 5 in the apache + license + +1999-07-31 12:02 millert + + * LICENSE, aclocal.m4, check.c, configure.in, insults.h, logging.c, + sudo.c, sudo.h, auth/rfc1938.c: there was a 1995 release too + +1999-07-28 05:24 millert + + * CHANGES: updates + +1999-07-28 05:21 millert + + * check.c: Use dirs instead of files for timestamp. This allows + tty and non-tty schemes to coexist reasonably. Note, however, + that when you update a tty ticket, the mtime on the user dir gets + updated as well. + +1999-07-28 05:17 millert + + * configure.in, configure: Fix getprpwnam() checking on SCO. Need + to link with "-lprot -lx" when linking test program, not just + -lprot. Also add check for getspnam(). The SCO docs indicate + that /etc/shadow can be used but this may be a lie. + +1999-07-24 03:35 millert + + * auth/API: first cut at auth API description + +1999-07-22 15:48 millert + + * auth/: fwtk.c, kerb4.c, kerb5.c, pam.c, rfc1938.c, secureware.c, + securid.c, sudo_auth.c, sudo_auth.h: auth API change. There is + now an init method that gets run before the main loop. This + allows auth routines to differentiate between initialization that + happens once vs. setup that needs to run each time through the + loop. + +1999-07-22 12:23 millert + + * logging.c, auth/kerb5.c: use easprintf() and evasprintf() + +1999-07-22 12:22 millert + + * alloc.c, sudo.h: add easprintf() and evasprintf(), error checking + versions of asprintf() and vasprintf() + +1999-07-22 09:14 millert + + * TODO: remove 2 items. One done, one won't do. + +1999-07-22 09:10 millert + + * sudo.man, visudo.man, sudo.cat, sudo.html, sudoers.html, + visudo.cat, visudo.html, configure, lex.yy.c: regen + +1999-07-22 09:06 millert + + * CHANGES: new changes + +1999-07-22 09:01 millert + + * sudo.pod: o Document -K flag and update meaning of -k flag. o + BSD-style copyright o Document clearing of BIND resolver + environment variables o Clarify bit about shared libs o suggest + rc files create /tmp/.odus if your OS gives away files + +1999-07-22 08:59 millert + + * visudo.pod: BSD license + +1999-07-22 08:58 millert + + * tgetpass.c: o BSD copyright o no need to block signals, we now do + that in main() o cosmetic changes + +1999-07-22 08:57 millert + + * testsudoers.c, visudo.c: o BSD-style copyright o Use "struct + sudo_user" instead of old globals. o some cometic cleanup + +1999-07-22 08:56 millert + + * sudo_setenv.c, version.h: BSD-style copyright + +1999-07-22 08:56 millert + + * sudo.h: o BSD copyright o logging and parser bits moved to their + own .h files o new "struct sudo_user" to encapsulate many of the + old globals. + +1999-07-22 08:55 millert + + * sudo.c: o no longer contains sudo 1.1/1.2 code o BSD copyright o + use new logging routines o simplified flow of control o BIND + resolver additions to badenv_table + +1999-07-22 08:53 millert + + * strerror.c: BSD-style copyright + +1999-07-22 08:53 millert + + * snprintf.c: Now compiles on more K&R compilers + +1999-07-22 08:52 millert + + * putenv.c: BSD-style copyright, cosmetic changes + +1999-07-22 08:51 millert + + * parse.c, parse.yacc, parse.h, parse.lex: BSD-style copyright. + Move parser-specific defines and structs into parse.h + other + cosmetic changes + +1999-07-22 08:51 millert + + * logging.h: defines for logging routines + +1999-07-22 08:49 millert + + * ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h, + interfaces.h, pathnames.h.in: BSD-style copyright + +1999-07-22 08:48 millert + + * find_path.c, getspwuid.c, goodpath.c, interfaces.c: BSD-style + copyright, cosmetic changes + +1999-07-22 08:46 millert + + * configure.in: o tgetpass.c is no longer optional o kill DCE_OBJS, + add AUTH_OBJS o kill --disable-tgetpass o add --without-passwd o + changes to fill in AUTH_OBJS for new auth api o check for + strerror(), v?snprintf() and v?asprintf() o replace + --with-AuthSRV with --with-fwtk + +1999-07-22 08:43 millert + + * config.h.in: BSD-style copyright. Remove USE_GETPASS and + HAVE_UTIME_NULL. Add HAVE_FWTK, HAVE_STRERROR, HAVE_SNPRINTF, + HAVE_VSNPRINTF, HAVE_ASPRINTF, HAVE_VASPRINTF, WITHOUT_PASSWD and + NO_PASSWD + +1999-07-22 08:42 millert + + * compat.h: BSD-style copyright; Add S_IFLNK and MIN/MAX id they + are missing. + +1999-07-22 08:39 millert + + * alloc.c: BSD-style copyright + +1999-07-22 08:38 millert + + * TROUBLESHOOTING: no more --with-getpass + +1999-07-22 08:34 millert + + * TODO: Take out things I've done... + +1999-07-22 08:34 millert + + * README: Refer to LICENSE + +1999-07-22 08:34 millert + + * PORTING: --with-getpass no longer exists + +1999-07-22 08:33 millert + + * Makefile.in: BSD-style copyright. Update to reflect reality wrt + new files and new auth modules. + +1999-07-22 08:32 millert + + * INSTALL: Remove --with-AuthSRV and --disable-tgetpass. Add + --with-fwtk and --without-passwd. + +1999-07-22 08:31 millert + + * HISTORY: Update history a bit + +1999-07-22 08:29 millert + + * COPYING, LICENSE: Now distributed under a BSD-style license + +1999-07-22 08:28 millert + + * auth/sudo_auth.c: o BSD-style copyright o Add support for + NO_PASSWD/WITHOUT_PASSWD options. o skey/opie replaced by + rfc1938 code o new struct sudo_user global + +1999-07-22 08:25 millert + + * auth/: pam.c, sia.c: BSD-style copyright and use new log + functions + +1999-07-22 08:24 millert + + * auth/kerb5.c: o BSD-style copyright o Use new log functiongs o + Use asprintf() and snprintf() where sensible. + +1999-07-22 08:19 millert + + * check.c: Rewrote all the old sudo 1.1/1.2 code. Timestamp + handling is now done more reasonably--better sanity checks and + tty-based stamps are now done as files in a directory with the + same name as the invoking user, eg. /var/run/sudo/millert/ttyp1. + It is not currently possible to mix tty and non-tty based ticket + schemes but this may change in the future (it requires sudo to + use a directory instead of a file in the non-tty case). Also, + ``sudo -k'' now sets the ticket back to the epoch and ``sudo -K'' + really deletes the file. That way you don't get the lecture + again just because you killed your ticket in .logout. BSD-style + copyright now. + +1999-07-22 08:13 millert + + * logging.c: o rewritten logging routines. log_error() now takes + printf-style varargs and log_auth() for the return value of + validate(). o BSD-style copyright + +1999-07-22 07:04 millert + + * auth.c, check_sia.c, dce_pwent.c, secureware.c: superceded by new + auth API + +1999-07-22 07:02 millert + + * auth/fwtk.c: Use snprintf() where it makes sense and add a + BSD-style copyright + +1999-07-22 07:00 millert + + * auth/: afs.c, aix_auth.c, dce.c, passwd.c, rfc1938.c, + secureware.c, securid.c, sudo_auth.h, kerb4.c: BSD-style + copyright + +1999-07-22 06:57 millert + + * emul/utime.h, utime.c: BSD-style copyright + +1999-07-22 06:57 millert + + * emul/search.h: this has been rewritten so use my BSD-style + copyright + +1999-07-15 11:21 millert + + * snprintf.c: include malloc.h if no stdlib.h + +1999-07-15 10:21 millert + + * snprintf.c: KTH snprintf()/asprintf() for systems w/o them + +1999-07-15 10:20 millert + + * strerror.c: strerror() for systems w/o it + +1999-07-12 06:53 millert + + * visudo.c: stylistic changes + +1999-07-12 06:25 millert + + * parse.c, parse.lex, parse.yacc: Add contribution info in the main + comment + +1999-07-11 16:10 millert + + * auth/pam.c: remove missed ref to PAM_nullpw + +1999-07-11 16:10 millert + + * auth/sudo_auth.h: pasto + +1999-07-11 15:19 millert + + * auth/kerb5.c: more or less complete now--still untested + +1999-07-11 15:09 millert + + * auth/: afs.c, pam.c: don't use user_name macro, it will go away + +1999-07-11 14:42 millert + + * auth/: opie.c, rfc1938.c, sudo_auth.h, skey.c: combine skey/opie + code into rfc1938.c + +1999-07-11 07:22 millert + + * auth/: dce.c, sudo_auth.h: DCE authentication method; basically + unchanged from dce_pwent.c + +1999-07-11 06:44 millert + + * auth/: aix_auth.c, sudo_auth.h: AIX authenticate() support. + Could probably be much better + +1999-07-11 06:43 millert + + * auth/sia.c: Fix an uninitialized variable and some cleanup. Now + works (tested) + +1999-07-11 05:37 millert + + * auth/: sia.c, sudo_auth.h: SIA support for digital unix + +1999-07-11 05:33 millert + + * auth/pam.c: don't use prompt global, it will go away + +1999-07-11 05:32 millert + + * auth/secureware.c: correct copyright years + +1999-07-10 20:32 millert + + * auth/: afs.c, fwtk.c, kerb4.c, sudo_auth.h, kerb5.c, opie.c, + pam.c, passwd.c, secureware.c, securid.c, skey.c, sudo_auth.c: + New authentication API and methods + +1999-07-08 06:46 millert + + * parse.yacc: only save an entry if user_matches && host_matches, + even if the stack is empty (fix for previous commit) + +1999-07-08 06:35 millert + + * parse.yacc: 1) Always save an entry on the stack if it is empty. + This fixes the -l and -v flags that were broken by earlier parser + changes. + + 2) In a Runas list, don't negate FALSE -> TRUE since that would + make !foo match any time the user specified a runas user (via -u) + other than foo. + +1999-07-08 05:45 millert + + * testsudoers.c: interfaces and num_interfaces are now auto, not + extern + +1999-07-07 14:09 millert + + * auth.c: use a static global to keep stae about empty passwords + +1999-07-07 14:08 millert + + * check_sia.c: make PASSWORD_NOT_CORRECT logging consistent with + other modules + +1999-07-05 16:53 millert + + * auth.c: PAM prompt code was wrong, looks like we have to kludge + it after all. + +1999-07-05 16:35 millert + + * auth.c: In the PAM code, when a user hits return at the first + password prompt, exit without a warning just like the normal auth + code + +1999-07-05 16:15 millert + + * configure, configure.in: kludge around cross-compiler false + positives + +1999-07-05 16:14 millert + + * auth.c, check.c, check_sia.c, logging.c, sudo.h, tgetpass.c: New + (correct) PAM code Tgetpass now takes an echo flag for use with + PAM_PROMPT_ECHO_ON Block SIGINT and SIGTSTP during auth remove a + useless umask setting Change error from BAD_ALLOCATION -> + BAD_AUTH_INIT (for use with sia/PAM) Some cosmetic changes to + auth.c for consistency + +1999-07-05 16:11 millert + + * sudo.c: Some -Wall and kill some trailing spaces + +1999-07-05 16:10 millert + + * configure.in: define -D__EXTENSIONS__ for solaris so we get + crypt() proto + +1999-06-22 09:42 millert + + * RUNSON: add Dynix 4.4.4 + +1999-06-22 09:30 millert + + * INSTALL, config.h.in, configure.in, configure: for kerberos V < + version, fall back on old kerb4 auth code + +1999-06-22 06:41 millert + + * INSTALL: clarify some things + +1999-06-22 06:38 millert + + * UPGRADE, sudoers.cat, sudoers.man, sudoers.pod: typos + +1999-06-14 19:47 millert + + * sudo.c: mention why DONT_LEAK_PATH_INFO is not the default + +1999-06-03 12:34 millert + + * tgetpass.c: Fix open(2) return value checking, was NULL for + fopen, should be -1 for open + +1999-06-03 12:06 millert + + * configure: regen + +1999-06-03 12:06 millert + + * configure.in: better wording for solaris pam notice + +1999-06-03 11:52 millert + + * CHANGES: document recent changes + +1999-06-03 11:52 millert + + * TROUBLESHOOTING: Update shadow password section + +1999-06-03 11:51 millert + + * auth.c: move authentication code from check.c to auth.c + +1999-06-03 11:51 millert + + * Makefile.in, check.c, sudo.h: move authentication code to auth.c + +1999-05-16 21:36 millert + + * Makefile.in, check.c, check_sia.c, compat.h, find_path.c, + getspwuid.c, goodpath.c, interfaces.c, interfaces.h, lex.yy.c, + logging.c, parse.c, parse.lex, parse.yacc, secureware.c, sudo.c, + sudo.h, sudo_setenv.c, testsudoers.c, tgetpass.c, visudo.c: Move + interface-related defines to interfaces.h so we don't have to + include everywhere. + +1999-05-14 12:30 millert + + * CHANGES, INSTALL, TODO, check.c, compat.h, getspwuid.c, + logging.c, parse.yacc, sudo.c, tgetpass.c: o Replace _PASSWD_LEN + braindeath with our own SUDO_MAX_PASS. + It turns out the old DES crypt does the right thing with + passwords + longert than 8 characters. + o Fix common typo (necesary -> necessary) + o Update TODO list + +1999-05-03 12:00 millert + + * sudo.c: set $LOGNAME when we set $USER + +1999-04-27 00:00 millert + + * INSTALL: add comment about digital unix and interfaces.c warning + with gcc + +1999-04-15 01:12 millert + + * sample.sudoers: use modern paths and give examples for some of + the new parser features + +1999-04-10 13:03 millert + + * parse.c: fix comment + +1999-04-10 00:49 millert + + * alloc.c, check.c, check_sia.c, dce_pwent.c, find_path.c, + getspwuid.c, goodpath.c, interfaces.c, lex.yy.c, logging.c, + parse.c, parse.lex, parse.yacc, putenv.c, secureware.c, sudo.c, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, visudo.c: + Function names should be flush with the start of the line so they + can be found trivially in an editor and with grep + +1999-04-10 00:40 millert + + * find_path.c, interfaces.c, lex.yy.c, parse.c, parse.lex, + parse.yacc, sudo.c, testsudoers.c, tgetpass.c, visudo.c: free(3) + is already void, no need to cast it + +1999-04-10 00:37 millert + + * logging.c, sudo.c, sudo.h: catch case where cmnd_safe is not set + (this should not be possible) + +1999-04-10 00:10 millert + + * CHANGES, logging.c, parse.c, parse.yacc, sudo.c, sudo.h, + testsudoers.c, visudo.c: Stash the "safe" path (ie: the one + listed in sudoers) to the command instead of stashing the struct + stat. Should be safer. + +1999-04-08 19:56 millert + + * INSTALL, Makefile.in, UPGRADE: notes on updating from an earlier + release + +1999-04-07 20:20 millert + + * CHANGES: updated + +1999-04-07 19:18 millert + + * parse.yacc, sudo.tab.h, sudoers.cat, sudoers.html, sudoers.man, + sudoers.pod: You can now specifiy a host list instead of just a + host or alias. Ie: user = host1,host2,ALIAS,!host3 my_command + now works. + +1999-04-07 02:59 millert + + * testsudoers.c: Quiet -Wall + +1999-04-07 02:50 millert + + * parse.yacc: Move the push from the beginning of cmndspec to the + end. This means we no longer have to do a push at the end of + privilege, just reset some values. + +1999-04-06 20:24 millert + + * sudoers.cat, sudoers.html, sudoers.man, sudoers.pod: runas-lists + and NOPASSWD/PASSWD modifiers are now sticky and you can use "!" + most everywhere + +1999-04-06 14:12 millert + + * sudoers.pod: modernize paths and update su example based on + sample.sudoers one + +1999-04-06 14:06 millert + + * sample.sudoers: New runas semantics + +1999-04-06 13:54 millert + + * CHANGES, Makefile.in, alloc.c, config.h.in, configure, + configure.in, strdup.c, sudo.h: In estrdup(), do the malloc + ourselves so we don't need to rely on the system strdup(3) which + may or may not exist. There is now no need to provide strdup() + for those w/o it. Also, the prototype for estrdup() was wrong, + it returns char * and its param is const. + +1999-04-06 13:40 millert + + * getcwd.c: $Sudo tag + +1999-04-06 13:20 millert + + * check.c: buf should be prompt; Michael Robokoff + + +1999-04-06 01:40 millert + + * CHANGES, TODO, parse.yacc: It is now possible to use the '!' + operator in a runas list as well as in a Cmnd_Alias, Host_Alias + and User_Alias. + +1999-04-06 01:38 millert + + * logging.c, sudo.h: Kill GLOBAL_NO_SPW_ENT (not used) and crank + GLOBAL_PROBLEM + +1999-04-06 01:08 millert + + * sudo.h: Definitions of *_matched were wrong--user top, not top-2 + as subscript. + +1999-04-06 01:00 millert + + * logging.c, parse.c, parse.yacc, sudo.c, sudo.h: Add + VALIDATE_NOT_OK_NOPASS for when user is not allowed to run a + command but the NOPASSWD flag was set. Make runasspec, + runaslist, runasuser, and nopasswd typeless in parse.yacc Add + support for '!' in the runas list Fix double printing of '%' and + '+' for groups and netgroups respectively Add *_matched macros + (no need for local stack variable). Should only be used directly + after a pop (since top must be >= 2). + +1999-04-05 23:25 millert + + * aclocal.m4, configure.in: Add copyright, somewhat silly + +1999-04-05 16:57 millert + + * BUGS, INSTALL, Makefile.in, README, alloc.c, check.c, + check_sia.c, compat.h, config.h.in, configure, configure.in, + dce_pwent.c, find_path.c, getspwuid.c, goodpath.c, ins_2001.h, + ins_classic.h, ins_csops.h, ins_goons.h, insults.h, interfaces.c, + lex.yy.c, logging.c, parse.c, parse.lex, parse.yacc, + pathnames.h.in, putenv.c, secureware.c, strdup.c, sudo.c, + sudo.cat, sudo.h, sudo.man, sudo_setenv.c, sudoers.cat, + sudoers.man, testsudoers.c, tgetpass.c, utime.c, version.h, + visudo.c, visudo.cat, visudo.man, emul/utime.h: Crank version to + 1.6 and combine copyright statements + +1999-04-05 16:30 millert + + * sample.sudoers: Use ! not ^ to do negation + +1999-04-05 16:29 millert + + * lex.yy.c: regen + +1999-04-05 16:28 millert + + * parse.yacc, parse.lex: Make runas and NOPASSWD tags persistent + across entris in a command list. Add a PASSWD tag to reverse + NOPASSWD. When you override a runas or *PASSWD tag the value + given becomes the new default for the rest of the command list. + +1999-04-02 16:03 millert + + * CHANGES, RUNSON: update for 1.5.9 + +1999-04-02 16:02 millert + + * visudo.c: Shift return value of system(3) by 8 to get real exit + value and if it is not 1 or 0 print the retval along with the + error message. + +1999-03-30 16:45 millert + + * Makefile.in: testsudoers needs LIBOBJS too + +1999-03-30 12:17 millert + + * parse.c, parse.yacc: Fix another parser bug. For a sudoers entry + like this: millert ALL=/bin/ls,(daemon) !/bin/ls sudo + would not allow millert to run ls as root. + +1999-03-30 01:08 millert + + * CHANGES: new change + +1999-03-30 01:03 millert + + * parse.yacc: Save entries that match a ! command on the matching + stack too + +1999-03-30 01:01 millert + + * sudo.c: Make sudo's usage info better when mutually exclusive + args are given and don't rely on argument order to detect this; + nick@zeta.org.au + +1999-03-29 15:03 millert + + * CHANGES, Makefile.in, RUNSON: updates from CU + +1999-03-28 23:38 millert + + * Makefile.in: use gzip + +1999-03-28 23:31 millert + + * parse.yacc: Fix off by one error introduced in *alloc changes + +1999-03-28 23:05 millert + + * BUGS, CHANGES, INSTALL, Makefile.in, README, alloc.c, check.c, + check_sia.c, compat.h, config.h.in, configure, configure.in, + dce_pwent.c, find_path.c, getspwuid.c, goodpath.c, ins_2001.h, + ins_classic.h, ins_csops.h, ins_goons.h, insults.h, interfaces.c, + lex.yy.c, logging.c, parse.c, parse.lex, parse.yacc, + pathnames.h.in, putenv.c, secureware.c, strdup.c, sudo.c, + sudo.cat, sudo.h, sudo.man, sudo_setenv.c, sudoers.cat, + sudoers.man, testsudoers.c, tgetpass.c, utime.c, version.h, + visudo.c, visudo.cat, visudo.html, visudo.man, visudo.pod, + emul/utime.h: ++version + +1999-03-28 21:59 millert + + * Makefile.in, check.c, find_path.c, getspwuid.c, goodpath.c, + interfaces.c, lex.yy.c, logging.c, parse.c, parse.lex, + parse.yacc, putenv.c, secureware.c, strdup.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, utime.c, visudo.c: Use + emalloc/erealloc/estrdup + +1999-03-28 20:29 millert + + * alloc.c: error checking memory allocation routines + +1999-03-28 19:23 millert + + * parse.yacc: Still not right, this fixes it for real + +1999-03-28 19:08 millert + + * parse.yacc: Fix for previous commit + +1999-03-28 19:05 millert + + * CHANGES, INSTALL, parse.yacc: Fix a parser bug that was exposed + when mixing different runas specs and ! commands. For example: + millert ALL=(daemon) /usr/bin/whoami,!/bin/ls would + allow millert to run whoami as root as well as daemon when it + should just allow daemon. The problem was that comma-separated + commands in a list shared the same entry on the matching stack. + Now they get their own entry iff there is a full match. It may + be better to just make the runas spec persistent across all + commands in a list like the user and host entries of the matching + stack. However, since that is a fairly major change it should + gets its own minor rev increase. + +1999-03-28 13:50 millert + + * check.c, config.h.in: Simplify PAM code and fix a PAM-related + warning on Linux + +1999-03-26 13:17 millert + + * CHANGES: updates + +1999-03-26 13:12 millert + + * sample.sudoers: better su entry + +1999-03-26 13:10 millert + + * configure: regen + +1999-03-26 13:09 millert + + * check.c, configure.in: new pam code that works on solaris, should + work on linux too; aelberg@home.com + +1999-03-19 14:44 millert + + * RUNSON: more entries + +1999-03-19 14:43 millert + + * config.h.in: only include strings.h if there is no string.h + +1999-03-17 15:25 millert + + * config.guess: Sinix is now being called ReliantUNIX; + bjjackso@us.oracle.com + +1999-03-13 13:37 millert + + * sudo.c: shost must be set before log functions are called #ifdef + HOST_IN_LOG + +1999-03-07 18:34 millert + + * CHANGES, lex.yy.c, parse.lex: Fix a bug wrt quoting characters in + command args. Stop processing an arg when you hit a backslash so + the quoted-character detection can catch it. + +1999-02-26 01:19 millert + + * interfaces.c: include sys/time.h; aparently AIX needs it. + ppz@cdu.elektra.ru + +1999-02-23 19:43 millert + + * configure, configure.in: add missing case statement so + --without-sendmail works + +1999-02-22 21:51 millert + + * CHANGES: more + +1999-02-22 15:10 millert + + * configure, configure.in: only search for -lsun in irix <= 4.x + +1999-02-22 15:01 millert + + * configure, configure.in: back out last configure.in change now + that I've hacked autoconf to fix the real problem and add a + missing newline + +1999-02-22 14:32 millert + + * CHANGES: updated + +1999-02-22 14:05 millert + + * getcwd.c: add def of dirfd() for those without it + +1999-02-22 10:58 millert + + * configure.in, configure: When falling back to checking for + socket() when linking with "-lsocket -lnsl" check for main() + instead since autoconf has already cached the results of checking + for socket() in -lsocket. This is really an autoconf bug as it + should use the extra libs as part of the cache variable name. + +1999-02-22 10:47 millert + + * configure.in: typo + +1999-02-21 15:18 millert + + * configure.in: fix occurrence of $with_timeout that should be + $with_password_timeout; + Michael.Neef@neuroinformatik.ruhr-uni-bochum.de + +1999-02-17 11:40 millert + + * sudo.cat, sudo.html, sudo.man, sudo.pod: fix grammar; + espie@openbsd.org + +1999-02-11 01:41 millert + + * parse.yacc, sudo.c, testsudoers.c: add cast for strdup in places + it does not have it + +1999-02-09 13:11 millert + + * configure, configure.in: define for_BSD_TYPES irix + +1999-02-06 19:47 millert + + * Makefile.in, sudo.cat, sudo.html, sudo.man, sudo.pod: Make it + clear that it is the user's password, not root's, that we want. + +1999-02-06 19:43 millert + + * check.c, sudo.h: If the user enters an empty password and really + has no password, accept the empty password they entered. + Perviously, they could enter anything *but* an empty password. + Also, add GETPASS macro that calls either tgetpass() or getpass() + depending on how sudo was configured. Problem noted by + jdg@maths.qmw.ac.uk + +1999-02-02 23:32 millert + + * Makefile.in, check.c, check_sia.c, compat.h, config.h.in, + dce_pwent.c, find_path.c, getspwuid.c, goodpath.c, ins_2001.h, + ins_classic.h, ins_csops.h, ins_goons.h, insults.h, interfaces.c, + logging.c, parse.c, parse.lex, parse.yacc, pathnames.h.in, + putenv.c, secureware.c, strdup.c, sudo.c, sudo.h, sudo_setenv.c, + testsudoers.c, tgetpass.c, utime.c, version.h, visudo.c, + emul/utime.h: add explicate copyright + +1999-02-02 23:16 millert + + * CHANGES: mention -lsocket, -lnsl configure changes + +1999-02-02 17:54 millert + + * sudo.c: Don't clobber errno after calling check_sudoers(). + +1999-01-31 19:46 millert + + * configure.in, configure: When linking with both -lsocket and + -lnsl be sure to do so in that order. Also, when we can't find + socket() or inet_addr() and have to try linking with both libs, + issue a warning. + +1999-01-31 19:45 millert + + * sudo.cat, sudo.man, sudo.pod: clarify bad timestamp and fmt + +1999-01-23 12:18 millert + + * INSTALL, RUNSON: be clear that pam is linux-only and add a RUNSON + entry + +1999-01-22 13:13 millert + + * configure, CHANGES, INSTALL, configure.in: fix and correctly + document --with-umask; problem noted by adap@adap.org + +1999-01-19 20:38 millert + + * configure.in, configure: only use /usr/{man,catman}/local to + store man pages if suer didn't override prefix or mandir + +1999-01-19 20:24 millert + + * configure, INSTALL, configure.in: fix typo, make --with-SecurID + take an arg + +1999-01-18 21:53 millert + + * RUNSON: updates from users + +1999-01-18 21:04 millert + + * CHANGES, INSTALL, check.c, configure, configure.in: FWTK + 'authsrv' support from Kevin Kadow + +1999-01-18 20:00 millert + + * configure, configure.in: better fix for the problem of unresolved + symbols in -lnsl or -lsocket + +1999-01-18 19:39 millert + + * configure, configure.in: when checking for functions in -lnsl and + -lsocket link with both of them to avoid unresolved symbols on + some weirdo systems + +1999-01-17 20:49 millert + + * BUGS, CHANGES, RUNSON, TODO: old changes that didn't make it into + RCS before the RCS->CVS switch + +1999-01-17 18:16 millert + + * Makefile.in, check.c, check_sia.c, compat.h, config.h.in, + configure.in, dce_pwent.c, find_path.c, getspwuid.c, goodpath.c, + ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h, + interfaces.c, lex.yy.c, logging.c, lsearch.c, parse.c, parse.lex, + parse.yacc, pathnames.h.in, putenv.c, secureware.c, strdup.c, + sudo.c, sudo.pod, sudo_setenv.c, sudoers.pod, testsudoers.c, + tgetpass.c, utime.c, visudo.c, visudo.pod, emul/search.h, + emul/utime.h: add sudo tags + +1999-01-17 17:53 millert + + * version.h, sudo.h: testing Sudo tag + +1999-01-17 17:40 millert + + * BUGS, INSTALL, Makefile.in, README, check.c, check_sia.c, + compat.h, config.h.in, configure, configure.in, dce_pwent.c, + find_path.c, getspwuid.c, goodpath.c, ins_2001.h, ins_classic.h, + ins_csops.h, ins_goons.h, insults.h, interfaces.c, lex.yy.c, + logging.c, parse.c, parse.lex, parse.yacc, pathnames.h.in, + putenv.c, secureware.c, strdup.c, sudo.c, sudo.cat, sudo.h, + sudo.man, sudo_setenv.c, sudoers.cat, sudoers.man, testsudoers.c, + tgetpass.c, utime.c, version.h, visudo.c, visudo.cat, visudo.man, + emul/utime.h: crank version and regen files + +1999-01-17 17:27 millert + + * Makefile.in: kill rcs goop in update_version and fix now that + version is a const + +1999-01-17 17:08 millert + + * INSTALL, check.c, config.h.in, configure, configure.in, + logging.c, sudo.c, sudo.h, sudo.pod: kerb5 support from + fcusack@iconnet.net + +1999-01-17 16:45 millert + + * realpath.c, sudo_realpath.c: we no longer use realpath + +1999-01-17 16:44 millert + + * qualify.c: replaced by find_path.c + +1999-01-17 16:43 millert + + * options.h: all options are now configure flags + +1999-01-17 16:42 millert + + * lex.yy.c: regen + +1999-01-17 16:41 millert + + * getwd.c: superceded by getcwd.c + +1999-01-17 16:36 millert + + * getpass.c: superceded by tgetpass.c + +1999-01-17 16:36 millert + + * SUPPORTED: superceded by RUNSON + +1999-01-17 16:33 millert + + * OPTIONS: No longer used now that we have configure options for + everything. + +1999-01-17 16:32 millert + + * configure: regen based on configure.in + +1999-01-17 16:31 millert + + * sudo.man, sudoers.man, visudo.man, sudo.cat, sudo.html, + sudoers.cat, visudo.cat, sudoers.html, visudo.html: regen based + on sudo.pod, sudoers.pod, and visudo.pod + +1998-12-11 12:16 millert + + * check.c: fix tty tickets in remove_timestamp (didn't use ':') + +1998-12-07 16:16 millert + + * interfaces.c: close sock when we are done with it + +1998-11-27 19:37 millert + + * parse.yacc: never say "error on line -1" + +1998-11-23 23:38 millert + + * configure.in: check for -lnsl before -lsocket + +1998-11-23 23:29 millert + + * configure.in: quote '[', ']' used in ranges correctly + +1998-11-21 17:54 millert + + * config.h.in: add missing NO_ROOT_SUDO noted by drno@tsd.edu + +1998-11-20 18:33 millert + + * version.h: 1.5.7 + +1998-11-20 18:33 millert + + * INSTALL: more info for 1.5.7 + +1998-11-20 18:30 millert + + * README: update for 1.5.7 + +1998-11-20 14:26 millert + + * parse.yacc: make increases of cm_list_size and ga_list_size be + similar to increases of stacksize (ie: >= not > in initial + compare). + +1998-11-20 14:22 millert + + * parse.yacc: when we get a syntax error, report it for the + previous line since that's generally where the error occurred. + +1998-11-18 15:31 millert + + * config.h.in, configure.in, interfaces.c: add back check for + sys/sockio.h but only use it if SIOCGIFCONF is not defined + +1998-11-18 15:25 millert + + * config.h.in: define BSD_COMP for svr4 + +1998-11-17 23:16 millert + + * check.c, check_sia.c, find_path.c, getcwd.c, getspwuid.c, + goodpath.c, interfaces.c, logging.c, lsearch.c, parse.c, + parse.lex, parse.yacc, putenv.c, secureware.c, strdup.c, sudo.c, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, visudo.c: more + -Wall + +1998-11-17 23:10 millert + + * configure.in: kill check for sockio,h + +1998-11-17 23:10 millert + + * config.h.in: no more HAVE_SYS_SOCKIO_H + +1998-11-17 22:51 millert + + * check.c, check_sia.c, find_path.c, getcwd.c, getspwuid.c, + goodpath.c, interfaces.c, logging.c, lsearch.c, parse.c, + parse.lex, parse.yacc, putenv.c, secureware.c, strdup.c, sudo.c, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, visudo.c: + -Wall + +1998-11-16 17:38 millert + + * sudo.c: add missing inform_user() + +1998-11-13 19:21 millert + + * find_path.c: return NOT_FOUND if given fully qualified path and + it does not exist previously it would perror(ENOENT) which + bypasses the option to not leak path info + +1998-11-13 19:20 millert + + * configure.in: for kerb5, check for -lkerb4, fall back on -lkrb + for kerb, check for -ldes + +1998-11-13 14:19 millert + + * INSTALL: tty tickets are user:tty now + +1998-11-13 14:10 millert + + * check.c: when using tty tickets make it user:tty not user.tty as + a username could have a '.' in it + +1998-11-09 19:15 millert + + * sudo.c: add "ignoring foo found in ." for auth successful case + +1998-11-09 17:57 millert + + * sudo.c: add missing printf param + +1998-11-08 15:56 millert + + * INSTALL, config.h.in, configure.in, find_path.c, sudo.c, sudo.h: + go back to printing "command not found" unless + --disable-path-info specified. Also, tell user when we ignore + '.' in their path and it would have been used but for + --with-ignore-dot. + +1998-11-08 13:51 millert + + * check.c, sudo.c: Only one space after a colon, not two, in + printf's + +1998-11-05 12:59 millert + + * sudo.pod: document setting $USER + +1998-11-04 22:24 millert + + * check.c: fix bugs with prompt expansion + +1998-11-04 21:21 millert + + * sudo.c: set $USER for root too + +1998-11-04 17:13 millert + + * getspwuid.c: typo + +1998-11-04 17:07 millert + + * configure.in: HP-UX's iscomsec is in -lsec, not libc + +1998-11-03 22:24 millert + + * configure.in: remove some entries in the OS case statement that + did nothing + +1998-11-03 22:19 millert + + * TROUBLESHOOTING: add "cd" section and flush out syslog section + +1998-11-03 20:51 millert + + * Makefile.in: no more sudo-lex.yy.c + +1998-11-03 20:50 millert + + * check_sia.c: add custom prompt support + +1998-11-03 20:40 millert + + * sudo.c: kill perror("malloc") since we already have a good error + messages pw_ent -> pw for brevity set $USER if -u specified + +1998-11-03 20:39 millert + + * parse.c: kill perror("malloc") since we already have a good error + messages pw_ent -> pw for brevity when checking if %group + matches, look up user in password file so that %groups works in a + RunAs spec. + +1998-11-03 20:39 millert + + * logging.c, parse.yacc: kill perror("malloc") since we already + have a good error messages + +1998-11-03 20:38 millert + + * check.c, getspwuid.c, interfaces.c, testsudoers.c: kill + perror("malloc") since we already have a good error messages + pw_ent -> pw for brevity + +1998-11-03 15:03 millert + + * tgetpass.c: the prompt is expanded before tgetpass is called + +1998-11-03 15:03 millert + + * sudo.h: tgetpass now has the same args as getpass again + +1998-11-03 15:02 millert + + * getspwuid.c: add iscomsec, issecure support + +1998-11-03 15:02 millert + + * check.c: we now expand any %h or %u in the prompt before passing + to tgetpass + +1998-11-03 14:58 millert + + * configure.in: add check for syslog(3) in -lsocket, -lnsl, -linet + +1998-11-03 14:56 millert + + * config.h.in: add HAVE_ISCOMSEC and HAVE_ISSECURE + +1998-11-03 14:55 millert + + * configure.in: add check for iscomsec in HP-UX + +1998-11-03 14:51 millert + + * configure.in: check for issecure if we have getpwanam on SunOS + some options are incompatible with DUNIX SIA check for dispcrypt + on DUNIX + +1998-10-25 15:21 millert + + * config.h.in: add HAVE_DISPCRYPT + +1998-10-25 15:21 millert + + * secureware.c: add back support for non-dispcrypt based checking + for older DUNIX + +1998-10-25 00:51 millert + + * INSTALL: sia changes + +1998-10-25 00:48 millert + + * configure.in: SIA becomes the default on Digital UNIX now havbe + --disable-sia to turn it off... + +1998-10-24 23:52 millert + + * check.c: move local includes after system ones + +1998-10-24 19:28 millert + + * check.c, check_sia.c, sudo.h: add pass_warn() which prints out + INCORRECT_PASSWORD or an insult to stderr + +1998-10-24 19:07 millert + + * check_sia.c: fix while loop in sia_attempt_auth() that checks the + password. Only the first iteration was working. + +1998-10-21 21:00 millert + + * aclocal.m4: don't trust UID_MAX or MAXUID + +1998-10-21 20:35 millert + + * configure.in: fix two pastos + +1998-10-21 20:30 millert + + * configure.in: fix typo + +1998-10-21 20:19 millert + + * getspwuid.c, secureware.c: init crypt_type to INT_MAX since it is + legal to be negative in DUNX 5.0 + +1998-10-21 20:15 millert + + * configure.in: for secureware on dunix, use -lsecurity -ldb -laud + -lm but check for -ldb since DUNX < 4.0 lacks it + +1998-10-21 19:50 millert + + * check.c, compat.h, config.h.in, configure.in, getspwuid.c, + secureware.c, sudo.c, tgetpass.c: getprpwuid is broken in HP-UX + 10.20 at least (it sleeps for 2 minutes if the shadow files don't + exist). + +1998-10-20 17:22 millert + + * INSTALL: updated --with-editor blurb + +1998-10-20 17:21 millert + + * TROUBLESHOOTING: tell how to put sudoers in a different dir + +1998-10-20 16:22 millert + + * configure.in: add missing quotes around $with_editor + +1998-10-20 14:00 millert + + * configure.in: typo in --with-editor bits + +1998-10-20 01:24 millert + + * INSTALL: I don't expect it to work on Solaris + +1998-10-20 01:24 millert + + * check.c: add back security/pam_misc.h + +1998-10-19 17:13 millert + + * INSTALL: remove dunix note since configure checks for this now + +1998-10-19 16:30 millert + + * configure.in: add check for broken dunix prot.h (4.0 < 4.0D is + bad) + +1998-10-19 14:32 millert + + * getspwuid.c, secureware.c, tgetpass.c: new dunix shadow code, use + dispcrypt(3) + +1998-10-19 14:32 millert + + * config.h.in: add HAVE_INITPRIVS + +1998-10-19 14:31 millert + + * sudo.c: call initprivs() if we have it for getprpwuid later on + +1998-10-19 14:30 millert + + * Makefile.in: clean pathnames.h too + +1998-10-19 14:28 millert + + * configure.in: quote "Sorry, try again." with [] since it has a + comma in it set LIBS when we add stuff to SUDO_LIBS set + SECUREWARE when we find getprpwuid() so we can check for + bigcrypt, set_auth_parameters, and initprivs later. + +1998-10-19 13:48 millert + + * INSTALL: update Digital UNIX note about acl.h + +1998-10-18 20:26 millert + + * INSTALL: add --with-sia --without-root-sudo -> + --disable-root-sudo some reordering + +1998-10-18 20:22 millert + + * secureware.c: add whitespace + +1998-10-18 20:22 millert + + * Makefile.in, check.c, config.h.in, configure.in, logging.c, + sudo.h: add SIA support + +1998-10-18 20:21 millert + + * check_sia.c: Initial revision + +1998-10-18 19:42 millert + + * configure.in: when checking for -lsocket, -lnsl, and -linet, + check for the specific functions we need from them. + +1998-10-18 19:10 millert + + * config.h.in, sudo.h: move Syslog_* defs into sudo.h + +1998-10-18 18:15 millert + + * sudo.h, Makefile.in: added check_secureware + +1998-10-18 18:12 millert + + * configure.in: finished adding AC_MSG_CHECKING and AC_MSG_RESULT + bits + +1998-10-18 18:00 millert + + * insults.h: don't define CLASSIC_INSULTS and CSOPS_INSULTS if no + other sets defined. configure now does that for us + +1998-10-18 17:45 millert + + * configure.in: move some --with options around change a bunch of + echo's to AC_MSG_CHECKING, AC_MSG_RESULT pairs + +1998-10-18 01:09 millert + + * configure.in: change $with_foo-bar -> $with_foo_bar kill extra " + that caused a syntax error add some echo verbage + +1998-10-17 18:08 millert + + * check.c: moved SecureWare stuff into secureware.c + +1998-10-17 18:07 millert + + * secureware.c: Initial revision + +1998-10-17 17:02 millert + + * INSTALL: update url to solaris gcc bins + +1998-10-17 16:39 millert + + * INSTALL: change option formatter and flesh out someentries + +1998-10-17 16:18 millert + + * sudo.pod, visudo.pod, TROUBLESHOOTING: environmental variable -> + environment variable + +1998-10-17 16:01 millert + + * BUGS: everything is now done via configure + +1998-10-17 16:00 millert + + * README: prev rev was 1.5.6 + +1998-10-17 00:33 millert + + * Makefile.in: passing SUDOERS_MODE, SUDOERS_UID, SUDOERS_GID + correctly + +1998-10-17 00:32 millert + + * config.h.in: SUDOERS_MODE, SUDOERS_UID, SUDOERS_GID now come from + the Makefile + +1998-10-17 00:31 millert + + * Makefile.in: merge OSDEFS and OPTIONS into DEFS get sudoers_uid, + sudoers_gid, sudoers_mode from configure + +1998-10-17 00:30 millert + + * configure.in: SUDOERS_MODE, SUDOERS_UID, and SUDOERS_GID now get + substituted into the Makefile, not config.h + +1998-10-17 00:30 millert + + * INSTALL: document all --with/--enable options + +1998-10-15 02:25 millert + + * insults.h: options.h is no more + +1998-10-15 02:25 millert + + * config.h.in: assimilated options.h + +1998-10-15 02:24 millert + + * configure.in: moved options from options.h to configure + +1998-10-15 01:41 millert + + * check.c, find_path.c, getspwuid.c, goodpath.c, interfaces.c, + logging.c, parse.c, parse.lex, parse.yacc, sudo.c, sudo.pod, + sudo_setenv.c, visudo.c: no more options.h + +1998-10-15 01:39 millert + + * INSTALL, Makefile.in, PORTING, TROUBLESHOOTING: remove references + to options.h + +1998-10-15 01:32 millert + + * interfaces.c, dce_pwent.c, sudo.c: kill sys/time.h + +1998-10-15 00:10 millert + + * tgetpass.c: if select return < -1 still prompt for pw + +1998-10-15 00:03 millert + + * options.h: convert LOGGING, LOGFAC, MAXLOGFILELEN, + IGNORE_DOT_PATH into configure options + +1998-10-14 23:57 millert + + * parse.c: FAST_MATCH is no longer an optino + +1998-10-14 23:52 millert + + * check.c: remove_timestamp() if timestamp is preposterous + +1998-10-14 23:36 millert + + * options.h: convert more options to --with/--enable + +1998-10-14 23:36 millert + + * INSTALL, aclocal.m4: logfile -> logpath + +1998-10-14 23:31 millert + + * configure.in: convert more options into --with and --enable + +1998-10-14 23:28 millert + + * tgetpass.c: catch EINTR in select and restart + +1998-10-14 23:15 millert + + * logging.c: sys/errno -> errno + +1998-09-24 11:40 millert + + * sudo.c: UMASK -> SUDO_UMASK. + +1998-09-24 11:36 millert + + * check.c, logging.c: time.h, not sys/time.h + +1998-09-21 19:52 millert + + * logging.c: MAILER -> _PATH_SENDMAIL + +1998-09-21 00:06 millert + + * INSTALL, configure.in: no more --with-C2, now it is + --disable-shadow + +1998-09-21 00:00 millert + + * aclocal.m4, check.c, compat.h, config.h.in, configure.in, + getspwuid.c, sudo.c, tgetpass.c: new shadow password scheme. + Always include shadow support if the platform supports it and the + user did not disable it via configure + +1998-09-20 19:48 millert + + * configure.in: --with-getpass -> --{enable,disable}-tgetpass + +1998-09-20 19:16 millert + + * Makefile.in: pathnames.h -> pathnames.h.in + +1998-09-20 19:14 millert + + * check.c: fix version string + +1998-09-20 19:12 millert + + * check.c: move pam_conv to be static to auth function remove + pam_misc.h (solaris doesn't have one) + +1998-09-20 19:10 millert + + * aclocal.m4: _CONFIG_PATH_* -> _PATH_* or _PATH_SUDO_* kill + SUDO_PROG_PWD + +1998-09-20 19:10 millert + + * configure.in: munge pathnames.h.in -> pathnames.h kill + SUDO_PROG_PWD + +1998-09-20 19:10 millert + + * pathnames.h.in: convert to pathnames.h.in + +1998-09-18 20:20 millert + + * configure.in: fix typo in sysv4 matching case /. + +1998-09-18 01:29 millert + + * check.c: pam stuff needs to run as root, not user, for shadow + passwords + +1998-09-17 12:26 millert + + * Makefile.in, emul/utime.h, check.c, compat.h, config.h.in, + dce_pwent.c, find_path.c, getspwuid.c, goodpath.c, ins_2001.h, + ins_classic.h, ins_csops.h, ins_goons.h, insults.h, interfaces.c, + logging.c, options.h, parse.c, parse.lex, parse.yacc, + pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, visudo.c, + BUGS, INSTALL, README, configure.in: updated version + +1998-09-17 12:13 millert + + * check.c: user version.h for long message + +1998-09-17 11:53 millert + + * check.c: this is version 1.5.6 + +1998-09-16 13:42 millert + + * Makefile.in: remove errant backslash + +1998-09-14 22:25 millert + + * options.h, parse.yacc, pathnames.h.in: fix version string + +1998-09-14 22:02 millert + + * BUGS, CHANGES, TODO: updtaed for 1.5.6 + +1998-09-14 22:02 millert + + * RUNSON: updated for 1.5.6 + +1998-09-14 11:48 millert + + * interfaces.c: kill unused localhost_mask var copy if name to + ifr_tmp after we zero it + +1998-09-13 15:50 millert + + * INSTALL: Better description of new vs. old sudoers modes fix some + typos better description of /usr/ucb/cc gotchas on slowaris + +1998-09-13 15:49 millert + + * Makefile.in: add sample.pam + +1998-09-13 15:32 millert + + * sudo.c: set NewArgv[0] to user_shell, not basename(user_shell) + +1998-09-12 11:10 millert + + * README: mention TROUBLESHOOTING more fix some typos + +1998-09-11 20:30 millert + + * configure.in: move --enable/--disable to be after --with + +1998-09-11 20:30 millert + + * INSTALL: document --enable/--disable + +1998-09-11 20:26 millert + + * INSTALL: document --with-pam + +1998-09-11 19:47 millert + + * configure.in: Add message for pam users + +1998-09-11 19:27 millert + + * sample.pam: Initial revision + +1998-09-11 19:23 millert + + * config.h.in: fix HAVE_PAM + +1998-09-11 19:19 millert + + * check.c, config.h.in, configure.in: pam support, from Gary Calvin + + +1998-09-10 18:51 millert + + * config.h.in: add HOST_IN_LOG and WRAP_LOG + +1998-09-10 18:51 millert + + * logging.c: add WRAP_LOG and HOST_IN_LOG + +1998-09-10 18:37 millert + + * configure.in: add --enable-log-host and --enable-log-wrap + +1998-09-10 18:32 millert + + * aclocal.m4: use AC_DEFINE_UNQUOTED for --with-logfile and + --with-timedir + +1998-09-08 20:45 millert + + * compat.h: add howmany macro + +1998-09-08 20:43 millert + + * tgetpass.c: include sys/param.h to get howmany macro + +1998-09-07 20:42 millert + + * OPTIONS, options.h, parse.yacc, sudo.c, testsudoers.c, visudo.c: + add RUNAS_DEFAULT + +1998-09-07 12:51 millert + + * fnmatch.c: bring in stdio.h for NULL + +1998-09-07 12:50 millert + + * aclocal.m4: allow /bin/{ksh,bach} and /usr/bin/{ksh,bash} as sh + +1998-09-07 12:43 millert + + * sudo.c: use HAVE_SET_AUTH_PARAMETERS + +1998-09-07 12:42 millert + + * config.h.in: add HAVE_SET_AUTH_PARAMETERS + +1998-09-07 12:41 millert + + * configure.in: add *-*-hiuxmpp* add test for set_auth_parameters() + if secureware + +1998-09-07 12:39 millert + + * config.sub: add support for HI-UX/MPP SR220001 02-03 0 SR2201 + +1998-09-07 12:06 millert + + * interfaces.c: initialize previfname + +1998-09-07 11:51 millert + + * interfaces.c: Don't use SIOCGIFADDR, we don't need it Use + SIOCGIFFLAGS if we have it check ifr_flags against IFF_UP and + IFF_LOOPBACK instead of kludging it + +1998-09-07 11:49 millert + + * configure.in: typo + +1998-09-07 00:01 millert + + * Makefile.in: don't need special build line for sudo.tab.o + +1998-09-06 23:58 millert + + * Makefile.in: don't clean sudo.tab.[ch] + +1998-09-06 23:48 millert + + * sudo.c: Sudo should prompt for a password before telling the user + that a command could not be found. + +1998-09-06 23:47 millert + + * BUGS: for 1.5.6 + +1998-09-06 23:25 millert + + * INSTALL, README: no longer require yacc + +1998-09-06 23:19 millert + + * Makefile.in: typo + +1998-09-06 23:18 millert + + * Makefile.in: y.tab -> sudo.tab include pre-yacc'd parse.yacc + +1998-09-06 23:09 millert + + * parse.lex: include sudo.tab.h, not y.tab.h don't break out of + command args if you get a '=' + +1998-09-06 22:59 millert + + * insults.h: fix version , + +1998-09-06 22:57 millert + + * compat.h, ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h: + fix version + +1998-09-06 22:55 millert + + * getcwd.c: getcwd(3) from OpenBSD for those without it. + +1998-09-06 22:51 millert + + * sudo.h: HAVE_GETWD -> HAVE_GETCWD + +1998-09-06 22:49 millert + + * configure.in: pretend sunos doesn't have getcwd(3) since it opens + a pipe to getpwd! + +1998-09-06 22:41 millert + + * parse.c: use NAMLEN() macro + +1998-09-06 22:34 millert + + * fnmatch.c: remove duplicate include of string.h + +1998-09-06 22:28 millert + + * configure.in: call SUDO_TYPE_DEV_T and SUDO_TYPE_INO_T + +1998-09-06 22:28 millert + + * aclocal.m4: add SUDO_TYPE_DEV_T and SUDO_TYPE_INO_T + +1998-09-06 22:28 millert + + * config.h.in: add dev_t and ino_t + +1998-07-28 12:44 millert + + * check.c: fix OTP_ONLY for opie + +1998-06-24 12:22 millert + + * testsudoers.c, tgetpass.c: include stdlib.h for malloc proto + +1998-05-19 00:10 millert + + * Makefile.in: make update_version saner + +1998-05-18 23:32 millert + + * config.h.in: add HAVE_WAITPID, HAVE_WAIT3, and sudo_waitpid() + +1998-05-18 23:32 millert + + * configure.in: check for waitpid and wait3 or no waitpid + +1998-05-18 23:31 millert + + * logging.c: used waitpid or wait3 if we have 'em + +1998-05-02 14:16 millert + + * visudo.c: fix some fprintf args, ariel@oz.engr.sgi.com (Ariel + Faigon) + +1998-04-27 20:09 millert + + * configure.in: don't need to explicately mention -lsocket -lnsl + for sequent + +1998-04-25 01:56 millert + + * configure.in: dynix should not link with -linet + +1998-04-10 15:32 millert + + * INSTALL: mention that HP-UX doesn't ship with yacc + +1998-04-06 22:35 millert + + * check.c: ignore kerberos if we can't get the local realm + +1998-04-05 23:37 millert + + * configure.in, BUGS, INSTALL, README: ++version + +1998-04-05 23:36 millert + + * version.h: ++ + +1998-04-05 23:35 millert + + * Makefile.in, emul/utime.h, check.c, config.h.in, dce_pwent.c, + find_path.c, getspwuid.c, getcwd.c, goodpath.c, interfaces.c, + logging.c, parse.c, parse.lex, putenv.c, strdup.c, sudo.c, + sudo.h, sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, + visudo.c: updated version + +1998-04-05 23:34 millert + + * check.c, sudo.h: fix version + +1998-04-05 23:33 millert + + * getcwd.c: don't use popen/pclose. Do it inline. + +1998-04-05 23:25 millert + + * lsearch.c: add rcsid + +1998-04-05 23:21 millert + + * sudo.c: typo + +1998-04-05 23:17 millert + + * sudo.h, pathnames.h.in, compat.h, options.h, ins_2001.h, + insults.h, ins_classic.h, ins_goons.h, ins_csops.h, parse.yacc, + check.c: updated version + +1998-04-05 23:15 millert + + * check.c, find_path.c, parse.c, sudo.c, testsudoers.c: MAX* + 1 -> + MAX* + +1998-04-05 23:14 millert + + * Makefile.in: getwd.c -> getcwd.c + +1998-04-05 22:49 millert + + * config.h.in: kill HAVE_GETWD + +1998-04-05 22:49 millert + + * configure.in: getcwd, not getwd + +1998-04-05 22:48 millert + + * getcwd.c: use MAX* not MAX* + 1 always run pwd as using getwd() + defeats the purpose + +1998-03-31 00:15 millert + + * OPTIONS, options.h: add STUB_LOAD_INTERFACES + +1998-03-31 00:05 millert + + * Makefile.in, check.c, emul/utime.h, compat.h, config.h.in, + dce_pwent.c, find_path.c, getspwuid.c, getwd.c, goodpath.c, + ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h, + interfaces.c, logging.c, options.h, parse.c, parse.lex, + parse.yacc, pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, visudo.c: + updated version + +1998-03-30 23:54 millert + + * configure.in: support *-ccur-sysv4 and fix two typos + +1998-03-27 19:52 millert + + * configure.in: don't echo about with_logfile and with_timedir + +1998-03-27 19:49 millert + + * INSTALL: document --with-logfile and --with-timedir + +1998-03-27 19:46 millert + + * aclocal.m4: support --with-logfile and --with-timedir + +1998-03-27 19:46 millert + + * configure.in: Add --with-logfile and --with-timedir + +1998-03-27 19:27 millert + + * sudo.c: change size computation of NewArgv for UNICOS + +1998-02-18 20:10 millert + + * configure.in: treate -*-sysv4* like *-*-svr4 + +1998-02-18 18:19 millert + + * configure.in: fix spacing for --with-authenticate help + +1998-02-18 16:39 millert + + * Makefile.in, check.c, emul/utime.h, compat.h, config.h.in, + dce_pwent.c, find_path.c, getspwuid.c, getwd.c, goodpath.c, + ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h, + interfaces.c, logging.c, options.h, parse.c, parse.lex, + parse.yacc, pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, visudo.c: + updated version + +1998-02-18 16:23 millert + + * parse.yacc: fix off by one error in push macro + +1998-02-17 01:15 millert + + * configure.in: removed bogus alloca hack + +1998-02-17 01:15 millert + + * check.c: added AIX 4.x authenticate() support + +1998-02-17 01:11 millert + + * parse.yacc: include alloca.h if using bison and not gcc and it + exists. fixes an alloca problem on hpux 10.x + +1998-02-17 00:39 millert + + * INSTALL: mention --with-authenticate + +1998-02-17 00:37 millert + + * configure.in: added AIX authenticate() support + +1998-02-17 00:22 millert + + * config.h.in: add HAVE_AUTHENTICATE + +1998-02-16 23:58 millert + + * interfaces.c: dynamically size ifconf buffer + +1998-02-16 23:56 millert + + * configure.in: quote '[' and ']' + +1998-02-16 21:42 millert + + * Makefile.in, emul/utime.h, check.c, compat.h, config.h.in, + dce_pwent.c, find_path.c, getspwuid.c, getwd.c, goodpath.c, + ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h, + logging.c, options.h, parse.c, parse.lex, parse.yacc, + pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, visudo.c: + updated version + +1998-02-16 19:06 millert + + * visudo.pod: add ERRORS section + +1998-02-16 18:57 millert + + * TROUBLESHOOTING: add busy stmp file explanation + +1998-02-15 18:49 millert + + * configure.in: the name of the cached var that signals whether or + not you are cross compiling changed. It is now + ac_cv_prog_cc_cross + +1998-02-11 16:26 millert + + * INSTALL: mention glibc 2.07 is fixed wrt lsearch()\. + +1998-02-06 21:55 millert + + * sample.sudoers, sudoers.pod: better example of su but not root su + +1998-02-06 15:49 millert + + * Makefile.in, check.c, emul/utime.h, compat.h, config.h.in, + dce_pwent.c, find_path.c, getspwuid.c, getwd.c, goodpath.c, + ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h, + interfaces.c, logging.c, options.h, parse.c, parse.lex, + parse.yacc, pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, visudo.c: + updated version + +1998-02-06 15:48 millert + + * Makefile.in: correct regexp for updating version + +1998-02-06 14:05 millert + + * tgetpass.c: remove bogus flush of stderr spew prompt before + turning off echo. Seems to fix a weird problem where if sudo + complained about a bogus stamp file the user would sometimes not + have a chance to enter a password + +1998-02-06 14:05 millert + + * check.c: fix bogus flush of stderr + +1998-02-05 19:19 millert + + * sudo.c: close fd's <=2 not <=3 and move that chunk of code up + +1998-02-05 19:18 millert + + * configure.in: support hpux1[0-9] not just hpux10 + +1998-01-30 14:59 millert + + * parse.c: set sudoers_fp to nil after closing + +1998-01-24 01:05 millert + + * config.guess, config.sub: updated from autoconf 2.12 + +1998-01-24 00:50 millert + + * configure.in: add *-*-svr4 rule + +1998-01-22 22:53 millert + + * tgetpass.c: fix select usage for high fd's (dynamically allocate + readfds) + +1998-01-22 22:49 millert + + * check.c: kill extra whitespace + +1998-01-22 19:28 millert + + * sudo.c: do an initgroups() before running a command, unless the + target user is root. + +1998-01-22 12:22 millert + + * TROUBLESHOOTING: tell people to use tabs, not spaces, in + syslog.conf + +1998-01-21 01:56 millert + + * parse.lex, Makefile.in, config.h.in, getwd.c, strdup.c, putenv.c, + emul/utime.h, testsudoers.c, utime.c, dce_pwent.c: updated + version + +1998-01-21 01:32 millert + + * goodpath.c, sudo_setenv.c, interfaces.c, tgetpass.c, visudo.c: + updated version + +1998-01-21 01:29 millert + + * sudo.h, pathnames.h.in, options.h, compat.h, insults.h, + ins_2001.h, ins_classic.h, ins_goons.h, ins_csops.h, parse.yacc, + check.c, getspwuid.c, find_path.c, logging.c, parse.c, sudo.c: + updated version + +1998-01-21 01:20 millert + + * Makefile.in: more tweaks to update_version + +1998-01-21 01:19 millert + + * Makefile.in: fixed up update_version rule + +1998-01-21 00:55 millert + + * configure.in: ++version + +1998-01-21 00:53 millert + + * Makefile.in: removed supe of check.c + +1998-01-21 00:51 millert + + * INSTALL: ++version I missed + +1998-01-21 00:51 millert + + * RUNSON: updated + +1998-01-21 00:48 millert + + * Makefile.in, check.c, compat.h, config.h.in, dce_pwent.c, + find_path.c, getspwuid.c, getwd.c, goodpath.c, ins_2001.h, + ins_classic.h, ins_csops.h, ins_goons.h, insults.h, interfaces.c, + logging.c, options.h, parse.c, parse.lex, parse.yacc, + pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, version.h, + visudo.c, emul/utime.h, BUGS, INSTALL, README: updated version + +1998-01-21 00:47 millert + + * CHANGES: updated for 1.5.5 + +1998-01-21 00:35 millert + + * Makefile.in: add rules to update version stuff in files so I + don't need to do it by hand + +1998-01-21 00:04 millert + + * sudo.h: sudoers_fp is now extern + +1998-01-21 00:03 millert + + * sudo.c: in check_sudoers, cache the sudoers file handle in + sudoers_fp so we don't have to open it again in the parse. This + may help with weird solaris problems where EAGAIN sometime + occurrs. + +1998-01-21 00:02 millert + + * parse.c: sudoers file open is now done only in check_sudoers() so + we just do a rewind() instead of an open. May help people on + solaris who were getting EAGAIN. + +1998-01-16 11:43 millert + + * INSTALL: mention that newer glibc is fixed + +1998-01-13 12:58 millert + + * sudo.c: newer irix uses _RLDN32_* envariables for 32-bit binaries + so ignore _RLD* instead of _RLD_* + +1998-01-13 10:32 millert + + * parse.c: typo + +1998-01-13 10:19 millert + + * parse.c: fix that bug for real + +1998-01-13 02:39 millert + + * INSTALL: document Linux's libc6 brokenness. + +1998-01-13 02:00 millert + + * parse.yacc: -Wall + +1998-01-13 01:22 millert + + * RUNSON: updated + +1998-01-13 00:50 millert + + * TROUBLESHOOTING: remind people to HUP syslogd + +1998-01-13 00:05 millert + + * Makefile.in: add -O flag to tar + +1998-01-13 00:00 millert + + * TODO, RUNSON: updated + +1998-01-12 23:59 millert + + * sudo.pod: remove author's email addr. people should mail + sudo-bugs + +1998-01-12 23:49 millert + + * INSTALL: fix version + +1998-01-12 23:48 millert + + * README, check.c, compat.h, config.h.in, configure.in, + dce_pwent.c, find_path.c, getspwuid.c, getwd.c, goodpath.c, + ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h, + interfaces.c, logging.c, options.h, parse.c, parse.lex, + parse.yacc, pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, version.h, + visudo.c: ++version + +1998-01-12 23:44 millert + + * RUNSON: updated + +1998-01-12 23:42 millert + + * INSTALL, Makefile.in: ++version + +1998-01-12 23:41 millert + + * CHANGES: updated fort 1.5.4 + +1998-01-12 23:41 millert + + * check.c: exit(1) if user enters no passwd + +1998-01-12 23:37 millert + + * BUGS: ++version + +1998-01-12 23:10 millert + + * parse.c: commands can start with ./* not just /* -- fixes a + serious security hole. + +1997-12-21 18:17 millert + + * sudo.c: Don't set the tty variable to NULL when we lack a tty, + leave it as "unknown". + +1997-11-23 13:29 millert + + * sample.sudoers: fix usage of (username) in conjunction with , and + ! + +1997-11-23 13:28 millert + + * visudo.c: catch the case where the user is not in the passwd file + +1997-11-23 13:24 millert + + * tgetpass.c: use fileno(input) + 1 instead of getdtablesize() as + the nfds arg to select(2) + +1997-11-23 01:53 millert + + * sudo.c: define tty global to an initial value to avoid dumping + core in logging functions when passwd file is unavailable. + +1997-11-23 01:51 millert + + * sudo.c: do the set_perms(PERM_USER, sudo_mode) after we have + gotten the passwd entry + +1997-11-23 00:21 millert + + * sudo.pod: talk about problem of ALL + +1997-10-10 00:54 millert + + * README: new web location + +1997-10-10 00:54 millert + + * INSTALL: fdesc bug is fixed in Open/Net BSD + +1997-10-10 00:52 millert + + * HISTORY: updates from Nieusma + +1997-10-09 18:37 millert + + * dce_pwent.c: move compat.h after the system includes + +1997-08-06 14:58 millert + + * logging.c: save errno from being clobbered by wait(). From Theo + +1997-05-21 11:57 millert + + * compat.h: fix an occurence of setresuid -> setreuid (typo) + +1997-03-19 17:45 millert + + * install-sh: check for path to strip + +1997-01-15 19:05 millert + + * logging.c: deal with maxfilelen < 0 case + +1997-01-15 19:05 millert + + * OPTIONS: fixed descriptin + +1996-12-11 23:10 millert + + * sudo.c: correct error message if mode/owner wrong and not + statable by owner but is statable by root. + +1996-11-23 02:18 millert + + * config.guess, config.sub: autoconf 2.11 + +1996-11-16 14:42 millert + + * CHANGES, RUNSON, TODO: sudo 1.5.3. + +1996-11-14 15:08 millert + + * sudo.h, parse.yacc: command_alias -> generic_alias + +1996-11-13 22:50 millert + + * sample.sudoers: added Runas_Alias example and fixed syntax errors + +1996-11-13 22:50 millert + + * OPTIONS, options.h: updated MAILSUBJECT + +1996-11-13 22:49 millert + + * logging.c: added %h expansion + +1996-11-13 21:37 millert + + * Makefile.in, check.c, compat.h, config.h.in, dce_pwent.c, + find_path.c, getspwuid.c, getwd.c, goodpath.c, ins_2001.h, + ins_classic.h, ins_csops.h, ins_goons.h, insults.h, interfaces.c, + logging.c, options.h, parse.c, parse.lex, parse.yacc, + pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, version.h, + visudo.c, INSTALL, README, configure.in: ++version + +1996-11-13 20:01 millert + + * emul/utime.h, BUGS: ++version + +1996-11-13 19:45 millert + + * sudoers.pod: document Runas_Alias + +1996-11-13 19:22 millert + + * visudo.pod: q (uid) -> Q + +1996-11-13 19:21 millert + + * visudo.c: buffer oflow checking q (uit) -> Q if yyparse() fails + drop into whatnow + +1996-11-13 19:05 millert + + * parse.yacc: add size params to sprintf + +1996-11-13 19:04 millert + + * parse.lex: allow trailing space after '\\' but before '\n' + +1996-11-13 19:04 millert + + * find_path.c: off by one error in path size check + +1996-11-13 19:03 millert + + * check.c: sprintf paranoia + +1996-11-12 11:59 millert + + * parse.yacc: fixed more_aliases + +1996-11-12 11:58 millert + + * visudo.c: now warns if killed by signal ./ + +1996-11-11 10:49 millert + + * parse.yacc: fix Runas_Alias stuff Alias's in runas list now get + expanded (but it is gross) + +1996-11-10 20:32 millert + + * sudo.c: Can now deal with SUDOERS_UID == 0 and SUDOERS_MODE == + 0400 + +1996-11-10 20:08 millert + + * parse.yacc: add Runas_Alias support change FOO to FOO_ALIAS (ie: + USER_ALIAS) + +1996-11-10 20:02 millert + + * parse.lex: Add Runas_Alias and simplify a rule. + +1996-11-10 19:15 millert + + * parse.yacc: always store User_Alias's since they can be used + inside of a runas list. Sigh. Really need a Runas_Alias + instead. + +1996-10-30 18:04 millert + + * visudo.c: deal with case where there is no sudoers file + +1996-10-11 23:01 millert + + * TROUBLESHOOTING: added one + +1996-10-10 22:11 millert + + * HISTORY, testsudoers.c: developement -> development + +1996-10-10 22:08 millert + + * INSTALL: added a note + +1996-10-10 20:36 millert + + * RUNSON: for 1.5.2 + +1996-10-10 20:36 millert + + * CHANGES: updated + +1996-10-10 00:56 millert + + * PORTING: removed seteuid() notes + +1996-10-09 13:37 millert + + * compat.h: better seteuid() emulatino + +1996-10-09 13:36 millert + + * configure.in: added check for seteuid + +1996-10-09 13:36 millert + + * config.h.in: added HAVE_SETEUID + +1996-10-08 19:22 millert + + * configure.in: first stab at sequent support + +1996-10-08 19:21 millert + + * config.h.in: added HAVE_SYS_SELECT_H + +1996-10-08 19:21 millert + + * compat.h: sequent -> _SEQUENT_ + +1996-10-08 19:11 millert + + * compat.h: added seteuid() macro for DYNIX + +1996-10-08 18:54 millert + + * tgetpass.c: _AIX -> HAVE_SYS_SELECT_H + +1996-10-07 01:05 millert + + * emul/utime.h, check.c, compat.h, dce_pwent.c, find_path.c, + getspwuid.c, getwd.c, goodpath.c, ins_2001.h, ins_classic.h, + ins_csops.h, ins_goons.h, insults.h, interfaces.c, options.h, + pathnames.h.in, version.h, BUGS, INSTALL, Makefile.in, OPTIONS, + README, config.h.in, logging.c, parse.c, parse.lex, parse.yacc, + putenv.c, strdup.c, sudo_setenv.c, testsudoers.c, utime.c, + visudo.c, tgetpass.c: ++version + +1996-10-07 00:59 millert + + * sudo.pod: added -H and SUDO_PS1 + +1996-10-07 00:55 millert + + * configure.in: use SUDO_FUNC_FNMATCH + +1996-10-07 00:54 millert + + * aclocal.m4: added SUDO_FUNC_FNMATCH + +1996-10-07 00:53 millert + + * sudo.c: added -H flag + +1996-10-07 00:53 millert + + * sudo.h: added MODE_RESET_HOME / + +1996-10-05 00:00 millert + + * INSTALL: mention OPIE + +1996-10-04 23:59 millert + + * configure.in: added opie support + +1996-10-04 23:59 millert + + * check.c: added HAVE_OPIE and changed to *_OTP_* + +1996-10-04 23:58 millert + + * compat.h, config.h.in: added HAVE_OPIE + +1996-10-04 23:58 millert + + * OPTIONS, options.h: SKEY -> OTP + +1996-10-03 23:27 millert + + * check.c: moved fclose() in skey stuff. + +1996-10-03 19:53 millert + + * putenv.c: index -> strchr remove unnecesary stuff + +1996-10-03 19:43 millert + + * check.c: now call skeychallenge() to get challenge instead of + making one up ourselves. this way, we get extra goodies in the + prompt. + +1996-09-10 00:32 millert + + * CHANGES: added one + +1996-09-10 00:18 millert + + * parse.lex: allow logins to start with a number (YUCK!) + +1996-09-08 15:18 millert + + * TROUBLESHOOTING: added soalris 2.5 vs 2.4 note + +1996-09-08 15:15 millert + + * configure.in: DUNIX doesn't need -lnsl + +1996-09-07 20:22 millert + + * CHANGES: [no log message] + +1996-09-07 20:21 millert + + * check.c, compat.h, config.h.in, dce_pwent.c, find_path.c, + getspwuid.c, getwd.c, goodpath.c, ins_2001.h, ins_classic.h, + ins_csops.h, ins_goons.h, insults.h, interfaces.c, logging.c, + options.h, parse.c, parse.lex, parse.yacc, pathnames.h.in, + putenv.c, strdup.c, sudo.c, sudo.h, sudo_setenv.c, testsudoers.c, + tgetpass.c, utime.c, version.h, visudo.c: courtesan + +1996-09-07 20:13 millert + + * TROUBLESHOOTING, INSTALL, Makefile.in, PORTING, RUNSON, README: + courtesan + +1996-09-07 20:12 millert + + * visudo.pod: [no log message] + +1996-09-07 20:00 millert + + * sudo.pod, visudo.pod: courtesan + +1996-09-07 19:45 millert + + * HISTORY: added courtesan ./ + +1996-09-06 00:12 millert + + * sudo.c: added $SUDO_PROMPT support + +1996-09-04 17:19 millert + + * check.c: print long skey challemged to stderr, not stdout + +1996-08-31 23:10 millert + + * CHANGES: updated for 1.5.1 + +1996-08-31 23:07 millert + + * emul/utime.h: ++version + +1996-08-31 12:34 millert + + * RUNSON: updated for 1.5.1 + +1996-08-30 10:49 millert + + * check.c: use shost, not host for tgetpass + +1996-08-30 00:21 millert + + * OPTIONS, sudo.pod: documented %u and %h + +1996-08-29 20:40 millert + + * configure.in: fixed typo + +1996-08-29 20:37 millert + + * INSTALL, Makefile.in, README, check.c, compat.h, config.h.in, + dce_pwent.c, find_path.c, getspwuid.c, getwd.c, goodpath.c, + ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h, + interfaces.c, logging.c, options.h, parse.c, parse.lex, + parse.yacc, pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, version.h, + visudo.c: ++version + +1996-08-29 20:30 millert + + * BUGS: ++version + +1996-08-29 18:32 millert + + * configure.in, Makefile.in, version.h: ++version + +1996-08-29 17:58 millert + + * sudo.h: new tgetpass() params + +1996-08-29 17:58 millert + + * check.c: pass use and host to tgetpass + +1996-08-29 17:57 millert + + * tgetpass.c: added %u and %h escapes + +1996-08-29 16:56 millert + + * OPTIONS, options.h, check.c: added NO_MESSAGE + +1996-08-29 16:23 millert + + * configure.in: added cray (unicos) support + +1996-08-27 11:36 millert + + * OPTIONS, options.h, sudo.c: added SHELL_SETS_HOME + +1996-08-25 17:56 millert + + * INSTALL: added note about "make install" + +1996-08-25 17:50 millert + + * parse.yacc: changed length/size params from int to size_t + +1996-08-25 13:35 millert + + * OPTIONS: now get CSOPS insults as well by default + +1996-08-25 13:33 millert + + * insults.h: use csops insults too by default + +1996-08-25 13:31 millert + + * INSTALL, Makefile.in, README, config.h.in, configure.in, + version.h: version = 1.5 + +1996-08-25 13:27 millert + + * sudo.c: added runas_homedir + +1996-08-25 13:27 millert + + * TODO: updated for 1.5 + +1996-08-25 13:23 millert + + * RUNSON: updated for 1.5 + +1996-08-25 13:19 millert + + * CHANGES: 1.5 release + +1996-08-25 13:17 millert + + * INSTALL: added "upgrading" notes + +1996-08-22 14:00 millert + + * visudo.c: now do chmod and chown after edit of temp file and + before rename + +1996-08-18 12:52 millert + + * Makefile.in: ++version added INSTALL.configure + +1996-08-18 12:52 millert + + * version.h, configure.in: ++version + +1996-08-18 12:51 millert + + * TROUBLESHOOTING: [no log message] + +1996-08-18 12:50 millert + + * parse.yacc: added missing cast + +1996-08-17 20:37 millert + + * sudo.c: sets $HOME to pw_dir of runas user + +1996-08-17 20:02 millert + + * sudo.pod: document $HOME change + +1996-08-17 19:43 millert + + * sudo.pod: fixed up some wording + +1996-08-17 19:25 millert + + * check.c, dce_pwent.c, find_path.c, getspwuid.c, getwd.c, + goodpath.c, interfaces.c, logging.c, parse.c, parse.lex, + parse.yacc, putenv.c, strdup.c, sudo.c, sudo_setenv.c, + testsudoers.c, tgetpass.c, utime.c, visudo.c: ++version + +1996-08-17 19:19 millert + + * emul/utime.h, compat.h, ins_2001.h, ins_classic.h, ins_csops.h, + ins_goons.h, insults.h, options.h, pathnames.h.in, sudo.h: + ++version + +1996-08-17 19:18 millert + + * sudo.h: name nad type changes + +1996-08-17 19:17 millert + + * testsudoers.c: now works with new sudo + +1996-08-17 19:07 millert + + * parse.yacc: fixed some XXX + +1996-08-17 18:52 millert + + * parse.yacc: some variable name changes + comment headers for + functions. + +1996-08-17 18:41 millert + + * tgetpass.c: added extra paren's to make compilers happy + +1996-08-17 18:34 millert + + * sudo.c: [no log message] + +1996-08-17 18:30 millert + + * parse.c: now uses init_parser() if not in sudoers and tries + "list" or "validate" scold but don't be nasty. + +1996-08-17 18:29 millert + + * TROUBLESHOOTING: now can use upper case login names + +1996-08-17 18:29 millert + + * visudo.c: now uses init_parser() + +1996-08-17 18:28 millert + + * PORTING: added info about PASSWORD_TIMEOUT + +1996-08-17 18:28 millert + + * INSTALL, README: updated + +1996-08-17 18:28 millert + + * INSTALL.configure: Initial revision + +1996-08-17 18:27 millert + + * BUGS: fixed a bug , + +1996-08-17 18:27 millert + + * parse.yacc: now dynamically allocates memory for the stacks -- no + more overflows! + +1996-08-17 18:26 millert + + * sudo.pod: -l now explands command aliases + +1996-08-17 13:22 millert + + * parse.yacc: hacks to expand command aliases for `sudo -l' + +1996-08-17 13:22 millert + + * sudo.c: remove $ENV and $BASH_ENV (dangerous in ksh, posix sh, + and bash) + +1996-08-17 13:22 millert + + * sudo.h: added struct command_alias + +1996-08-17 13:20 millert + + * sudo.pod: fixed a bug + +1996-08-17 13:15 millert + + * lsearch.c: in compar() key should be first arg + +1996-08-15 15:48 millert + + * BUGS: fixed some bugs + +1996-08-15 15:47 millert + + * parse.yacc: can now deal with upcase HOST and USER names + +1996-08-15 15:47 millert + + * sudo.c: don't yell too loudly at non-sudoers if they do "sudo -l" + +1996-08-15 15:46 millert + + * sudo.pod: fixed thinko + +1996-08-15 15:46 millert + + * parse.c: fix comment + +1996-08-09 18:07 millert + + * parse.c, parse.yacc: added support for new `sudo -l' stuff + +1996-08-09 18:06 millert + + * sudo.c: now uses list_matches() + +1996-08-09 18:06 millert + + * sudo.h: added struct sudo_match + +1996-08-09 17:37 millert + + * configure.in: now more -lgnumalloc + +1996-08-01 13:12 millert + + * install-sh: added more paths for chown and whoami + +1996-07-31 10:41 millert + + * check.c: typo + +1996-07-30 13:45 millert + + * aclocal.m4: fixed DUNIX check for shadow pw + +1996-07-30 13:41 millert + + * tgetpass.c: now only turn off echo if it is already on. this + fixes a race when you use sudo in a pipelin + +1996-07-30 12:53 millert + + * INSTALL: updated + +1996-07-29 22:29 millert + + * configure.in: changed "test -z $foo && do_this" to if; then + construct + +1996-07-28 22:47 millert + + * configure.in: added missing defines of SHADOW_TYPE + +1996-07-26 14:10 millert + + * check.c: protect AUTH_CRYPT_OLDCRYPT and AUTH_CRYPT_C1CRYPT since + they are only in dunix 4.x + +1996-07-26 14:09 millert + + * getspwuid.c: added AUTH_CRYPT_C1CRYPT support + +1996-07-26 13:23 millert + + * parse.c: no longer return VALIDATE_NOT_OK if there was a runas + that didn't match. Now we can have runas stuff on more than one + line. + +1996-07-25 23:45 millert + + * configure.in: got rid of HAVE_C2_SECURITY SHADOW_TYPE is always + defined to something + +1996-07-25 23:45 millert + + * config.h.in: removed HAVE_C2_SECURITY added SPW_BSD + +1996-07-25 23:44 millert + + * compat.h, getspwuid.c, sudo.c, tgetpass.c: use SHADOW_TYPE + instead of HAVE_C2_SECURITY + +1996-07-25 23:44 millert + + * check.c: SHADOW_TYPE is always defined so just against its value + +1996-07-25 23:44 millert + + * aclocal.m4: added SUDO_CHECK_SHADOW_DUNIX + +1996-07-25 18:47 millert + + * sudoers.pod: * -> ?* in one example added another instance of + (runas) and one of NOPASSWD: + +1996-07-24 13:02 millert + + * configure.in: added back check for config.cache from other host + type + +1996-07-24 12:49 millert + + * parse.lex: removed an instance of \" + +1996-07-24 12:49 millert + + * sample.sudoers: added an example + +1996-07-24 12:44 millert + + * sudoers.pod: updated wrt new wildcard matching + +1996-07-24 10:28 millert + + * configure.in: new check for shadow passwords if we don't know + anything + +1996-07-24 10:28 millert + + * aclocal.m4: new SUDO_CHECK_SHADOW_GENERIC + +1996-07-24 02:19 millert + + * configure.in: added back check for -lsocket (oops) + +1996-07-24 02:16 millert + + * configure.in: better (working) check for shadow passwd type if we + know to use C2. + +1996-07-24 01:59 millert + + * configure.in: now uses AC_CANONICAL_HOST to figure out os type + +1996-07-24 01:59 millert + + * Makefile.in: added config.{guess,sub} + +1996-07-24 01:58 millert + + * aclocal.m4: removed unused stuff to figure out os type + +1996-07-23 22:58 millert + + * config.sub: added openbsd + +1996-07-23 22:54 millert + + * config.sub: Initial revision + +1996-07-23 22:40 millert + + * config.guess: Initial revision + +1996-07-23 21:18 millert + + * testsudoers.c: don't call fnmatch() with FNM_PATHNAME flag unless + it can only be a pathname. need to check against sudoers_args + even if user_args is nil + +1996-07-23 21:18 millert + + * parse.c: don't call fnmatch() with FNM_PATHNAME flag unless it + can only be a pathname need to check against sudoers_args even if + user_args is nil + +1996-07-23 18:52 millert + + * check.c: added support for AUTH_CRYPT_OLDCRYPT w/ DUNIX C2 + +1996-07-23 01:18 millert + + * testsudoers.c: now takes command line args and uses cmnd_args + +1996-07-23 01:10 millert + + * parse.lex: fill_args was adding an extra leading space + +1996-07-22 15:50 millert + + * visudo.c: fixed dummy command_matches() + +1996-07-22 15:50 millert + + * parse.yacc: fixed prototype + +1996-07-22 15:31 millert + + * sudo.h: added cmnd_args + +1996-07-22 15:31 millert + + * parse.yacc: now uses flat args string + +1996-07-22 15:30 millert + + * parse.c, parse.lex: now uses flat arg string + +1996-07-22 15:29 millert + + * visudo.c: added cmnd_args def + +1996-07-22 14:30 millert + + * sudo.c: now sets cmnd_args global + +1996-07-22 14:30 millert + + * logging.c: cmnd_args is now exported from sudo.[ch] + +1996-07-21 18:41 millert + + * parse.yacc: can't rely on cmnd_matches as much as I thought -- + added some $$ stuff back in to prevent namespace pollution + problems. + +1996-07-21 18:01 millert + + * parse.yacc: Simplified parse rules wrt runas and NOPASSWD (more + consistent). + +1996-07-20 00:45 millert + + * parse.lex: NOPASSWD may now have blanks before the ':' '(' only + starts a 'runas' if in the initial state to avoid collision with + command args + +1996-07-20 00:23 millert + + * configure.in: added checks for specific shadow passwd schemes + +1996-07-20 00:18 millert + + * aclocal.m4: added routines to check for specific shadow passwd + types + +1996-07-18 18:27 millert + + * configure.in: added support for ncr boxen + +1996-07-18 18:26 millert + + * aclocal.m4: added support for detecting ncr boxen + +1996-07-16 14:57 millert + + * configure.in: added sinix support + +1996-07-13 22:29 millert + + * TROUBLESHOOTING: added info about "config.cache from other other" + error. + +1996-07-13 22:22 millert + + * aclocal.m4: now makes sure you don't have a config.cache file + from another OS + +1996-07-13 21:36 millert + + * configure.in: now sets $LIBS when needed to configure links with + libs when doing tests hpux10 now uses SPW_SECUREWARE for C2 added + check for bigcrypt(3) if SPW_SECUREWARE + +1996-07-13 21:30 millert + + * getspwuid.c: fixed typo + +1996-07-13 21:05 millert + + * tgetpass.c: now include stuff for SPW_SECUREWARE to get + AUTH_MAX_PASSWD_LENGTH + +1996-07-13 21:05 millert + + * getspwuid.c: no more SPW_HPUX10 + +1996-07-13 21:04 millert + + * config.h.in: no more SPW_HPUX10 added HAVE_BIGCRYPT + +1996-07-13 21:04 millert + + * compat.h: now uses AUTH_MAX_PASSWD_LENGTH if SPW_SECUREWARE + +1996-07-13 21:04 millert + + * check.c: SPW_SECUREWARE now uses bigcrypt + +1996-07-13 18:24 millert + + * sample.sudoers: fixed 2 syntax errors + +1996-07-13 18:24 millert + + * sudoers: root may now run ALL as ALL + +1996-07-11 20:59 millert + + * interfaces.c: fixed a typo/thinko that broke BSD's with sa_len + +1996-07-08 16:08 millert + + * check.c, configure.in: updated AFS support + +1996-07-08 16:07 millert + + * TROUBLESHOOTING: added entry about /usr/ucb/cc + +1996-07-08 16:06 millert + + * INSTALL: prep no longer holds gcc binaries + +1996-07-08 15:48 millert + + * INSTALL: updated AFS note + +1996-07-08 15:43 millert + + * Makefile.in: added @AFS_LIBS@ + +1996-07-08 15:33 millert + + * compat.h: AFS allows long passwords + +1996-07-08 14:16 millert + + * testsudoers.c: fixed -u user support + +1996-07-08 14:16 millert + + * parse.c: sudo -v now groks VALIDATE_OK_NOPASS + +1996-07-08 13:30 millert + + * parse.yacc: fixed no_passwd vs. runas_matched + +1996-07-08 10:30 millert + + * TROUBLESHOOTING: took out stuff about NFS-mounting since it is no + longer an issue + +1996-07-08 10:30 millert + + * INSTALL: added --with-libraries > --with-libpath --with-incpath + +1996-07-08 10:21 millert + + * parse.yacc: was setting runas_matches to -1 in wrong place + +1996-07-08 09:58 millert + + * check.c: removed usersec.h which is not present in new AFS + versions + +1996-07-08 09:55 millert + + * tgetpass.c: now deals with timeout <= 0 + +1996-07-08 09:51 millert + + * OPTIONS: updated + +1996-07-08 00:04 millert + + * configure.in: BSD/OS >= 2.0 now uses shlicc instead of just gcc + +1996-07-07 22:30 millert + + * sudo.c: fixed backwards compatibility with sudo 1.4 sudoers mode + for root readable/writable filesystems + +1996-07-07 20:49 millert + + * Makefile.in: now gives INSTALL -c flag + +1996-07-07 20:34 millert + + * parse.yacc: slightly simpler initialization of no_passwd and + runas_matches + +1996-07-07 20:33 millert + + * testsudoers.c: added -u username support + +1996-07-07 20:32 millert + + * configure.in: improved --with-libraries support + +1996-07-07 16:27 millert + + * configure.in: added --with-incpath, --with-libpath, + --with-libraries + +1996-07-07 16:01 millert + + * parse.yacc: now initializes some fields that weren't getting set + to -1 pretty gross -- need a rewrite. + +1996-06-25 23:19 millert + + * alloca.c: removed emacs'isms + +1996-06-25 22:29 millert + + * configure.in: no longer add -lPW to *_LIBS since we include + alloca.c + +1996-06-25 22:29 millert + + * config.h.in: added HAVE_ALLOCA_H + +1996-06-25 22:28 millert + + * Makefile.in: added alloca.c + +1996-06-25 22:18 millert + + * alloca.c: Initial revision + +1996-06-25 21:58 millert + + * configure.in: ++version + +1996-06-25 19:32 millert + + * sudo.c: now set uid to 1 instead of nobody for PERM_SUDOERS since + nobody is not always set to a valid uid. + +1996-06-25 19:31 millert + + * OPTIONS: fixed entry for SUDO_MODE + +1996-06-25 18:02 millert + + * sudo.c: Fixed NFS-mounted sudoers file under solaris both uid + *and* gid were being set to -2. Now beat NFS to the punch and + set uid to "nobody" ourselves, preserving group 0 to read + sudoers. + +1996-06-25 18:02 millert + + * parse.c: moved set_perms(PERM_ROOT) to be before yyparse() + +1996-06-25 18:00 millert + + * logging.c: fixed a typo + +1996-06-25 18:00 millert + + * configure.in: no longer need AC_PROG_INSTALL + +1996-06-25 17:59 millert + + * Makefile.in: always use install-sh to avoid install(1)'s that use + get{pw,gr}nam + +1996-06-25 16:07 millert + + * INSTALL: make clean -> make distclean + +1996-06-20 01:17 millert + + * parse.yacc: removed some unnecsary if's + +1996-06-20 01:16 millert + + * Makefile.in, version.h: ++version + +1996-06-20 01:16 millert + + * parse.c, testsudoers.c: now includes netgroup.h + +1996-06-20 00:45 millert + + * interfaces.c: removed cats of ioctl to int since they didn't shut + up -Wall + +1996-06-20 00:43 millert + + * interfaces.c: explicately cast ioctl() to int since it it not + always declared + +1996-06-20 00:41 millert + + * sudo.h: added declarations for yyparse() and yylex() + +1996-06-20 00:27 millert + + * parse.yacc: fixed an occurence of '==' -> '=' + +1996-06-20 00:22 millert + + * config.h.in, configure.in: added check for netgroup.h + +1996-06-20 00:20 millert + + * sudo.c: fixed 2 compiler warnings + +1996-06-20 00:08 millert + + * sudo.c: SHELL_IF_NO_ARGS caused core dump since NewArg[cv] + weren't being initialized + +1996-06-19 13:53 millert + + * sudo.pod: fixed a typo + +1996-06-17 12:19 millert + + * parse.yacc: fixed a formatting thingie + +1996-06-17 12:16 millert + + * parse.c, parse.yacc: fixed -u support with multiple user lists on + a line + +1996-06-17 10:23 millert + + * configure.in: unixware needs -lgen + +1996-06-17 10:23 millert + + * README: updated ftp location + +1996-06-17 00:08 millert + + * sudoers.pod: add net_addr/netmask support + +1996-06-17 00:07 millert + + * sample.sudoers: added net_addr/mask example + +1996-06-17 00:02 millert + + * parse.lex, parse.c: added support for net_addr/netmask + +1996-06-15 20:13 millert + + * sudoers.pod: ^ -> ! + +1996-06-15 18:12 millert + + * RUNSON: updated for 1.4.3 + +1996-06-15 18:12 millert + + * CHANGES: udpated for 1.4.3 + +1996-06-15 18:11 millert + + * TROUBLESHOOTING, TODO, BUGS: updated + +1996-06-15 18:11 millert + + * sample.sudoers: updated with examples of new stuff + +1996-06-15 18:10 millert + + * INSTALL, README: ++version + +1996-06-15 18:01 millert + + * sudoers.pod: updated wrt -u and NOPASSWD + +1996-06-15 17:58 millert + + * sudo.pod: updated wrt -u and CAVEATS + +1996-06-08 23:15 millert + + * sudo.c: fixed usage() + +1996-06-08 22:57 millert + + * parse.lex: now use :foo: character classes (makes no diff for + generated lexer) + +1996-06-07 14:33 millert + + * check.c: fixed LONG_SKEY_PROMPT stuff + +1996-06-06 15:35 millert + + * visudo.c: fixed a comment + +1996-06-06 15:03 millert + + * lsearch.c: make more like NetBSD one -- now compiles w/o warnings + +1996-06-06 15:02 millert + + * emul/search.h: fixed decls of lsearch() + +1996-06-05 22:20 millert + + * config.h.in, configure.in, getspwuid.c: added SPW_HPUX10 + +1996-06-05 22:20 millert + + * check.c: hpux 10 uses bigcrypt() if C2 + +1996-06-04 19:57 millert + + * parse.c: now always uses fnmatch to match args + +1996-06-04 19:40 millert + + * tgetpass.c: back to using stdio instead of raw i/o since that + caused some problems + +1996-05-28 22:14 millert + + * sudo.c: now give usage warning if use -l,-v,-k with args + +1996-05-28 18:22 millert + + * sudo.c: NewArgc is now set to 1 for -l, -v, -k + +1996-05-28 12:50 millert + + * sudo.c: now sets sudoers to correct group if mode is 0400 + +1996-05-28 12:02 millert + + * install-sh: updated to version used by inn and bind + +1996-05-28 00:08 millert + + * configure.in: now uses -lgnumalloc if it exists + +1996-05-28 00:02 millert + + * Makefile.in: "make install" now sets uid/gid and mode on sudoers + if it exists + +1996-05-28 00:01 millert + + * sudo.c: rmeoved debugging statements + +1996-05-28 00:00 millert + + * parse.yacc: added a missing free() + +1996-05-27 23:58 millert + + * sudo.c: now uses user_gid instead of getegid (which was wrong + anyway) to set SUDO_GID Now sets command line args in + SUDO_COMMAND envariabled (logging.c depends on args being in the + environment) + +1996-05-27 23:57 millert + + * logging.c: now uses SUDO_COMMAND envariable to get command args + rather than building it up again. + +1996-05-27 22:42 millert + + * parse.c: now uses user_gid + +1996-05-27 20:02 millert + + * sudo.c: fixed off by one error in allocation NewArgv + +1996-05-27 20:01 millert + + * parse.c: in sudoers, 'command ""' now means command with no args + +1996-05-27 20:01 millert + + * configure.in: added check for fnmatch(3) and fnmatch.h + +1996-05-27 20:01 millert + + * config.h.in: added HAVE_FNMATCH + +1996-05-27 20:00 millert + + * Makefile.in: replaced wildcat.* with fnmatch.* + +1996-05-27 20:00 millert + + * testsudoers.c: now uses fnmatch() + +1996-05-27 19:38 millert + + * parse.c: now uses fnmatch() instead of wildmat a trailing star + (*) by itself now matches multiple args added support for + wildcards in the pathname in sudoers + +1996-05-25 19:23 millert + + * fnmatch.c: now includes compat.h and config.h + +1996-05-25 18:09 millert + + * config.h.in: added HAVE_FNMATCH_H + +1996-05-25 18:07 millert + + * configure.in: now checks for alloca() (if needed by bison or dce) + and links with -lPW if it contains alloca() and libv and compiler + do not. + +1996-05-25 18:03 millert + + * fnmatch.3, fnmatch.c, emul/fnmatch.h: Initial revision + +1996-04-28 22:38 millert + + * sudo.c: now fixes mode on sudoers if set to 0400 to aid in + upgrade + +1996-04-28 17:44 millert + + * Makefile.in: fixed pod2man usage + +1996-04-28 17:40 millert + + * configure.in, Makefile.in, version.h: ++version + +1996-04-28 17:20 millert + + * testsudoers.c, visudo.c: runas_user is now initialized to "root" + +1996-04-28 17:20 millert + + * sudo.h: removed PERM_FULL_ROOT + +1996-04-28 17:18 millert + + * sudo.c: runas_user defaults to "root" so no more need to + PERM_RUNAS + +1996-04-28 17:16 millert + + * parse.c: will now only running commands as root if there was no + runas list (or if root is in the runas list) + +1996-04-28 17:15 millert + + * logging.c: now logs "USER=%s" + +1996-04-28 17:12 millert + + * parse.yacc: runas_matches is now set to false if we get a + negative match + +1996-04-28 15:01 millert + + * parse.lex: make #uid work + some minor cleanup + +1996-04-27 21:04 millert + + * sample.sudoers: added support for NOPASSWD and "runas" from + garp@opustel.com / + +1996-04-27 21:03 millert + + * visudo.c: added support for "runas" from garp@opustel.com + replaced SUDOERS_OWNER with SUDOERS_UID, SUDOERS_GID added + support for SUDOERS_MODE + +1996-04-27 21:03 millert + + * testsudoers.c: added support for "runas" from garp@opustel.com + +1996-04-27 21:02 millert + + * sudo.h: added support for NO_PASSWD and runas from + garp@opustel.com replaced SUDOERS_OWNER with SUDOERS_UID and + SUDOERS_GID and added support fro SUDOERS_MODE + +1996-04-27 21:00 millert + + * sudo.c: added support for NO_PASSWD and runas from + garp@opustel.com replaced SUDOERS_OWNER with SUDOERS_UID and + SUDOERS_GID and added support fro SUDOERS_MODE + +1996-04-27 21:00 millert + + * parse.yacc: added support for NO_PASSWD and runas from + garp@opustel.com + +1996-04-27 20:58 millert + + * parse.c, parse.lex: added support for NO_PASSWD and runas from + garp@opustel.com + +1996-04-27 20:56 millert + + * logging.c: added support for SUDOERS_WRONG_MODE and "runas" + +1996-04-27 20:40 millert + + * configure.in: added --with-CC only link with -lshadow on linux + (with shadow pw) if libc lacks getspnam() + +1996-04-27 20:39 millert + + * OPTIONS, options.h: removed NO_PASSWD since it is not possible to + do this in the sudoers file itself. Replaced SUDOERS_OWNER with + SUDOERS_UID and SUDOERS_GID. Added SUDOERS_MODE. + +1996-04-27 20:26 millert + + * Makefile.in: now uses SUDOERS_UID and SUDOERS_GID + +1996-04-27 11:20 millert + + * INSTALL: added --with-CC + +1996-04-06 16:31 millert + + * parse.lex: added double quote support + +1996-04-06 16:29 millert + + * sudoers.pod: documented double quoting + +1996-04-05 16:53 millert + + * mkinstalldirs: Initial revision + +1996-04-05 16:53 millert + + * check.c: fixed some indentation + +1996-04-05 16:48 millert + + * Makefile.in: fixed a typo + +1996-04-04 19:39 millert + + * Makefile.in: added install-dirs . + +1996-04-04 14:16 millert + + * dce_pwent.c: new version from "Jeff A. Earickson" + + +1996-04-03 13:40 millert + + * configure.in: $CSOPS -> $with_csops (whoops, missed one) + +1996-04-03 13:40 millert + + * BUGS: updated + +1996-04-03 13:36 millert + + * parse.lex: FQHOST now has same constraints as non-FQHOST + +1996-04-02 19:00 millert + + * INSTALL: added note about OS's w/ shadow passwords turned on by + default + +1996-04-02 18:58 millert + + * configure.in: fixed a typo + +1996-04-02 18:48 millert + + * configure.in: added support for --without-THING sanitized shadow + pw situtation by adding support for --without-C2 + +1996-04-02 16:42 millert + + * tgetpass.c: fixed a typo wrt placement of an end paren + +1996-04-02 14:57 millert + + * check.c: was closing an fd that may not have been opened + +1996-03-21 19:55 millert + + * sudo.c, OPTIONS, options.h: added NO_PASSWD + +1996-03-19 19:40 millert + + * configure.in: now always use shadow pw on some arches + +1996-03-19 17:07 millert + + * configure.in: added pyramid support + +1996-03-19 17:04 millert + + * configure.in: no longer check for C2 if alternate passwd method + is used no longer check for some libs twice + +1996-03-19 17:00 millert + + * parse.yacc: moved fqdn stuff into parse.lex (FQHOST) + +1996-03-19 17:00 millert + + * parse.lex: added FQHOST rules + +1996-03-18 20:57 millert + + * tgetpass.c: now define TCSASOFT in necesary + +1996-03-18 20:31 millert + + * tgetpass.c: now uses read/write instead of stdio string goop to + avoid problems with select(2) + +1996-03-18 19:37 millert + + * OPTIONS, find_path.c, options.h: -DNO_DOT_PATH -> + -DIGNORE_DOT_PATH + +1996-03-17 16:18 millert + + * INSTALL: added note about no shadow auto-detect if using + alternate auth schemes + +1996-03-17 15:33 millert + + * configure.in: don't check for C2 if AFS or DCE (unless they said + --with-C2) + +1996-03-17 15:08 millert + + * testsudoers.c: now groks shost + +1996-03-17 15:01 millert + + * options.h, OPTIONS, find_path.c: added NO_DOT_PATH + +1996-03-16 14:43 millert + + * find_path.c: checkdot now works correctly + +1996-03-12 18:01 millert + + * configure.in: can't have DCE and C2 passwords both... + +1996-03-11 14:05 millert + + * parse.yacc, sudo.c, sudo.h, visudo.c: now uses shost even if not + FQDN + +1996-03-11 14:04 millert + + * configure.in: now looks for skey in /usr/lib and doesn't require + libskey to be in /usr/local/lib just because skey.h is (for my + netbsd box :-) + +1996-03-11 02:00 millert + + * aclocal.m4, config.h.in, pathnames.h.in: _SUDO_PATH_ -> + _CONFIG_PATH_ + +1996-03-10 21:01 millert + + * aclocal.m4, sudo.pod: /var/run/.odus -> /var/run/sudo + +1996-03-10 20:59 millert + + * pathnames.h.in: now uses _SUDO_PATH_TIMEDIR + +1996-03-10 20:59 millert + + * OPTIONS: udpated FQDN + +1996-03-10 20:58 millert + + * config.h.in: added _SUDO_PATH_TIMEDIR + +1996-03-10 20:58 millert + + * aclocal.m4, configure.in: added SUDO_TIMEDIR + +1996-03-10 20:58 millert + + * sudo.pod: updated wrt /var/run/sudo + +1996-03-10 20:16 millert + + * sudo.c, sudo.h: added support for shost if FQDN + +1996-03-10 20:14 millert + + * parse.yacc, visudo.c: now uses shost if FQDN + +1996-03-10 20:12 millert + + * check.c: Now use skeylookup() instead off skeychallenge() + +1996-02-27 20:41 millert + + * logging.c: mail_argv should not contain ALERTMAIL as it includes + "-t" + +1996-02-22 17:06 millert + + * INSTALL, Makefile.in, README, version.h, configure.in: ++version + +1996-02-22 16:27 millert + + * compat.h: added more _PASSWD_LEN stuff -- now uses PASS_MAX too + +1996-02-22 16:27 millert + + * tgetpass.c: now includes limits.h moved _PASSWD_LEN -> compat.h + +1996-02-05 19:20 millert + + * README, INSTALL: ++version + +1996-02-05 19:20 millert + + * Makefile.in: ++versoin + +1996-02-05 19:16 millert + + * Makefile.in: fixed a typo + +1996-02-05 19:16 millert + + * configure.in: ++version + +1996-02-05 18:53 millert + + * RUNSON: updated + +1996-02-05 18:47 millert + + * CHANGES: done for 1.4.1 (I hope) + +1996-02-05 18:45 millert + + * sudoers.pod: added info on wildcards + +1996-02-05 18:39 millert + + * sample.sudoers: added wildcard example + +1996-02-05 17:03 millert + + * Makefile.in: now uses *.pod to build *.man and *.cat & *.html + +1996-02-05 17:03 millert + + * configure.in: addedSUDO_PROG_BSHELL !ll + +1996-02-05 16:10 millert + + * visudo.pod: fixed up some formatting + +1996-02-05 16:10 millert + + * sudoers.pod: redid section describing sample sudoers stuff + +1996-02-05 16:10 millert + + * sudo.pod: fixed some formatting + +1996-02-04 22:50 millert + + * getspwuid.c: now treats "" as bourne shell + +1996-02-04 22:49 millert + + * Makefile.in: TESTOBJS nwo includes wildmat.o + +1996-02-04 22:48 millert + + * testsudoers.c: now works with NewArg[cv] + +1996-02-04 21:59 millert + + * sudo.c: removed an XXX (fixed it in getspwuid.c) + +1996-02-04 21:58 millert + + * aclocal.m4: added check for bourne shell + +1996-02-04 21:58 millert + + * pathnames.h.in: added _PATH_BSHELL + +1996-02-04 21:58 millert + + * config.h.in: added _SUDO_PATH_BSHELL + +1996-02-04 16:36 millert + + * visudo.c: unixware vi returns 256 instead of 0 + +1996-02-04 16:24 millert + + * INSTALL: added Linux note + +1996-02-04 16:13 millert + + * logging.c: fixed up some XXX's. file log format now looks a + little more like real syslog(3) format. + +1996-02-04 16:13 millert + + * README, TROUBLESHOOTING: updated wrt lex/flex + +1996-02-04 16:11 millert + + * Makefile.in: commented out rule to build lex.yy.c from parse.lex + since we ship with a pre-flex'd parser + +1996-02-04 16:09 millert + + * parse.c, parse.yacc, visudo.c: path_matches -> command_matches + +1996-02-04 02:28 millert + + * logging.c: eliminated some strcat()'s + +1996-02-04 02:10 millert + + * configure.in: no longer checks for lex/flex (now assumes flex) + +1996-02-04 02:08 millert + + * configure.in: now checks for $kerb_dir_candidate/krb.h instead of + just kerb_dir_candidate + +1996-02-02 20:48 millert + + * parse.yacc: now use a 'hook' expression instead of an iffy one + :-) + +1996-02-02 01:14 millert + + * visudo.c: now works with new sudo arg stuff + +1996-02-02 01:14 millert + + * parse.yacc: fixed dereferencing deadbeef + +1996-02-01 23:53 millert + + * sudo.c: changed an occurrence of Argv to NewArgv + +1996-02-01 23:53 millert + + * parse.lex: took out support for quoted commands since there is no + need... + +1996-02-01 23:52 millert + + * parse.c: fixed a typo in a for() loop + +1996-02-01 23:52 millert + + * logging.c: protected against dereferencing rogue pointers + +1996-02-01 22:34 millert + + * sudo.c: now uses NewArgv amd NewArgc so cmnd_aegs is no longer + needed this also allows us to eliminate some kludges in + parse_args() and eliminate superfluous code. + +1996-02-01 22:34 millert + + * logging.c: no longer uses cmnd_args, now uses NewArgv instead. + +1996-02-01 22:32 millert + + * sudo.h: added struct sudo_command, NewArgc, and NewArgv removed + cmnd_args (no longer used) + +1996-02-01 22:31 millert + + * Makefile.in: added wildmat.c to SRCS & SUDOBJS + +1996-02-01 22:30 millert + + * parse.yacc: COMMAND is now a struct containing the path and args + +1996-02-01 22:30 millert + + * parse.lex: replaced append() with fill_cmnd() and fill_args. + command args from a sudoers entry are now stored in an arrary for + easy matching. + +1996-02-01 22:28 millert + + * parse.c: command line args from sudoers file are now in an array + like ones passed in from the command line + +1996-01-31 20:59 millert + + * parse.c: wildwat stuff now works + +1996-01-29 00:44 millert + + * version.h: ++version + +1996-01-29 00:44 millert + + * Makefile.in: ++version added wildmat.* + +1996-01-28 17:55 millert + + * parse.lex: added support for quoted commands (w/ or w/o args) + +1996-01-22 01:55 millert + + * sudo.pod, visudo.pod: cleaned up formatting + +1996-01-21 20:53 millert + + * sudo.pod, visudo.pod: Initial revision + +1996-01-21 02:07 millert + + * sudoers.pod: looks reasonable, could be mroe readable + +1996-01-20 23:47 millert + + * sudoers.pod: Initial revision + +1996-01-16 14:38 millert + + * RUNSON: updated + +1996-01-16 14:37 millert + + * OPTIONS: updated NO_ROOT_SUDO entry + +1996-01-15 11:37 millert + + * RUNSON: [no log message] + +1996-01-15 11:34 millert + + * sudo.c: fixed SECURE_PATH + +1996-01-14 20:55 millert + + * RUNSON: udpa`ted for 1.4 + +1996-01-14 20:52 millert + + * configure.in: AIX aixcrypt.exp now uses $(srcdir) + +1996-01-14 20:32 millert + + * TROUBLESHOOTING: added entry for anal ansi compilers + +1996-01-14 16:13 millert + + * INSTALL: added info on libcrypt_i for SCO + +1996-01-14 16:05 millert + + * TODO: [no log message] + +1996-01-14 15:39 millert + + * sample.sudoers: added comments + +1996-01-14 15:25 millert + + * TODO: 1.4 release + +1996-01-14 15:22 millert + + * README, config.h.in, configure.in, CHANGES: ++version + +1996-01-14 15:21 millert + + * BUGS: ++version and fixed ISC + +1996-01-14 15:19 millert + + * check.c, compat.h, dce_pwent.c, find_path.c, getspwuid.c, + getwd.c, goodpath.c, ins_2001.h, ins_classic.h, ins_csops.h, + ins_goons.h, insults.h, options.h, pathnames.h.in, sudo.h, + logging.c, putenv.c, strdup.c, sudo.c, sudo_setenv.c, + testsudoers.c, tgetpass.c, utime.c, visudo.c, INSTALL, OPTIONS: + ++version + +1996-01-14 15:16 millert + + * interfaces.c: added STUB_LOAD_INTERFACES ++version + +1996-01-14 15:14 millert + + * Makefile.in, version.h, parse.c, parse.lex, parse.yacc, + emul/utime.h: ++version + +1996-01-14 15:13 millert + + * PORTING: added info about fd_set in tgetpass added info on + interfaces.c + +1996-01-11 13:22 millert + + * dce_pwent.c: added sudo header + +1996-01-11 13:04 millert + + * tgetpass.c: fixed a typo + +1996-01-11 13:01 millert + + * Makefile.in: tgetpass.o is now only linked in with sudo (not + visudo) + +1996-01-09 12:56 millert + + * BUGS, INSTALL, OPTIONS, README, Makefile.in, config.h.in, + configure.in: ++version + +1996-01-09 12:54 millert + + * emul/utime.h: added copyright notice + +1996-01-09 12:52 millert + + * check.c, compat.h, find_path.c, getspwuid.c, getwd.c, goodpath.c, + ins_2001.h, ins_classic.h, ins_csops.h, ins_goons.h, insults.h, + interfaces.c, logging.c, options.h, parse.c, parse.lex, + parse.yacc, pathnames.h.in, putenv.c, strdup.c, sudo.c, sudo.h, + sudo_setenv.c, testsudoers.c, tgetpass.c, utime.c, version.h, + visudo.c: ++version + +1996-01-09 12:46 millert + + * tgetpass.c: minor cleanup and now includes sys/bsdtypes for + svr4'ish boxen + +1996-01-09 12:42 millert + + * configure.in: ISC now gets -lcrypt now check for sys/bsdtypes.h + +1996-01-09 12:41 millert + + * config.h.in: added check for sys/bsdtypes.h + +1996-01-07 16:00 millert + + * parse.yacc: removed debugging stuff (setting freed ptr to NULL) + +1996-01-07 15:55 millert + + * TROUBLESHOOTING: added 2 entries + +1996-01-07 15:55 millert + + * Makefile.in: added FAQ + +1996-01-07 14:26 millert + + * TROUBLESHOOTING: added section on syslog + +1996-01-07 14:25 millert + + * configure.in: added AC_ISC_POSIX for better ISC support + +1996-01-07 14:25 millert + + * config.h.in: fixed typo + +1996-01-07 14:25 millert + + * config.h.in: added define for _POSIX_SOURCE + +1996-01-04 00:41 millert + + * configure.in: fixed check for lsearch() + +1995-12-21 21:53 millert + + * interfaces.c: fixed for AIX now deal if num_interfaces == 0 + (should not happen) + +1995-12-20 17:02 millert + + * configure.in: now only define HAVE_LSEARCH if there is a + corresponding search.h + +1995-12-20 15:52 millert + + * interfaces.c: works on ISC again + +1995-12-18 17:36 millert + + * configure.in: now define HAVE_LSEARCH if we find lsearch() in + libcompat + +1995-12-18 17:32 millert + + * lsearch.c: char * -> const char * + +1995-12-18 17:29 millert + + * configure.in: now looks in -lcompat for lsearch() + +1995-12-18 17:23 millert + + * Makefile.in: remove sudo.core visudo.core for clan target + +1995-12-17 22:53 millert + + * aclocal.m4: added UID_MAX support in check for MAX_UID_T_LEN + +1995-12-17 22:36 millert + + * Makefile.in: fixed another occurence of sudo_getpwuid.* + +1995-12-17 22:30 millert + + * getspwuid.c, Makefile.in: sudo_getpwuid.c -> getspwuid.c + +1995-12-17 22:22 millert + + * configure.in: moved the "echo" + +1995-12-17 22:09 millert + + * CHANGES, BUGS, INSTALL, Makefile.in, OPTIONS, README, check.c, + compat.h, config.h.in, configure.in, find_path.c, getspwuid.c, + getwd.c, goodpath.c, ins_2001.h, ins_classic.h, ins_csops.h, + ins_goons.h, insults.h, interfaces.c, logging.c, options.h, + parse.c, parse.lex, parse.yacc, pathnames.h.in, putenv.c, + strdup.c, sudo.c, sudo.h, sudo_setenv.c, testsudoers.c, + tgetpass.c, utime.c, version.h, visudo.c: ++version + +1995-12-17 22:04 millert + + * testsudoers.c: added group support + +1995-12-17 22:00 millert + + * sample.sudoers: added group entry + +1995-12-17 21:59 millert + + * sudoers.man: documented group support + +1995-12-17 21:50 millert + + * parse.c, parse.lex, visudo.c, parse.yacc: added group support + +1995-12-15 17:45 millert + + * check.c: tkfile was too short and overflowed the kerberos realm + +1995-12-11 17:09 millert + + * sudo.c: now copy command args directly from Argv + +1995-12-11 15:55 millert + + * sudo.c: replaced code to copy cmnd_args so that is does not use + realloc since most realloc()'s really stink + +1995-12-08 14:11 millert + + * configure.in: syslog() fixed in hpux 10.01 + +1995-12-06 17:45 millert + + * configure.in: AC_CHECK_LIB() now sets SUDO_LIBS (and VISUDO_LIBS + if appropriate) + +1995-12-06 17:30 millert + + * configure.in: better error if cannot find skey incs or libs + +1995-12-06 17:26 millert + + * aclocal.m4: now use a temp file for determining max len of uid_t + in string form. the old hacky way broke on netbsd + +1995-12-05 19:02 millert + + * sudo.c: added set of parens and a space + +1995-12-05 18:58 millert + + * dce_pwent.c: fixes from Jeff Earickson , + +1995-12-05 18:58 millert + + * check.c: modified a comment + +1995-12-05 18:57 millert + + * Makefile.in: fixed up testsudoers target + +1995-12-05 18:56 millert + + * configure.in: DCE changes from Jeff Earickson + LIBS -> SUDO_LIBS and VISUDO_LIBS LDFLAGS -> + SUDO_FDFLAGS and VISUDO_LDFLAGS + +1995-12-05 18:17 millert + + * Makefile.in: LIBS -> SUDO_LIBS , VISUDO_LIBS LDFLAGS -> + SUDO_LDFLAGS, VISUDO_LDFLAGS + +1995-11-27 23:32 millert + + * configure.in: fix for C2 on hpux 10 now uses -linet if it exists + +1995-11-27 23:17 millert + + * check.c: LONG_SKEY_PROMPT is less of a klusge / + +1995-11-27 23:17 millert + + * configure.in: fixed typos w/ dce stuff + +1995-11-27 23:14 millert + + * Makefile.in: added dce_pwent.c + +1995-11-26 13:48 millert + + * INSTALL: amended section on combining authentication mechanisms + +1995-11-26 13:48 millert + + * PORTING: minor updates for 1.3.6 + +1995-11-26 13:47 millert + + * TROUBLESHOOTING: added 2 more entries + +1995-11-26 13:39 millert + + * BUGS: updated for 1.3.6 + +1995-11-26 13:39 millert + + * README: overhauled + +1995-11-25 21:23 millert + + * INSTALL: rewrote for sudo 1.3.6 + +1995-11-25 21:23 millert + + * TROUBLESHOOTING: added 3 entries + +1995-11-25 13:53 millert + + * find_path.c, getspwuid.c, sudo.c: added explict casts for strdup + since many includes don't prototype it. gag me. + +1995-11-25 13:23 millert + + * sudo.h: removed prototype for sudo_getpwuid() since convex C + compiler choked on it. + +1995-11-25 13:23 millert + + * sudo.c: added prototype for sudo_getpwuid() + +1995-11-25 13:23 millert + + * lsearch.c: now compiles on strict ANSI compilers + +1995-11-24 23:56 millert + + * check.c: added LONG_SKEY_PROMPT support + +1995-11-24 23:55 millert + + * Makefile.in: added extra $'s for make to eat up, yum. + +1995-11-24 23:38 millert + + * OPTIONS, options.h: added LONG_SKEY_PROMPT + +1995-11-24 18:48 millert + + * check.c: s/key support now works with normal s/key as well as + logdaemon + +1995-11-24 18:46 millert + + * options.h, OPTIONS: added SKEY_ONLY + +1995-11-24 18:46 millert + + * compat.h: set _PASSWD_LEN to 256 for any of KERB4, DCE, SKEY + +1995-11-24 00:42 millert + + * INSTALL: added DCE note added more AIX notes + +1995-11-24 00:39 millert + + * sudo.c: now include pthread.h for DCE support + +1995-11-23 22:22 millert + + * check.c: dce_pwent() is ok after all ., + +1995-11-23 22:21 millert + + * logging.c: now uses SYSLOG() macro that equates to either + syslog() or syslog_wrapper + +1995-11-23 21:44 millert + + * dce_pwent.c: minor formatting changes. renamed check() to + somthing less generic + +1995-11-23 21:27 millert + + * check.c, logging.c, parse.yacc, sudo.c, sudo.h, testsudoers.c, + visudo.c: now uses user_pw_ent and simple macros to get at the + contents + +1995-11-22 20:35 millert + + * check.c: simpler dec unix C2 support + +1995-11-22 20:35 millert + + * getspwuid.c: now sets crypt_type for DEC unix C2 + +1995-11-21 18:00 millert + + * configure.in: added csops paths for skey + +1995-11-21 16:27 millert + + * getspwuid.c: now includes string.h for strdup() prototype + +1995-11-21 01:47 millert + + * getspwuid.c: fixed a few typos + +1995-11-20 22:59 millert + + * check.c: now includes skey.h + +1995-11-20 22:10 millert + + * getspwuid.c: fixed up comments + +1995-11-20 22:04 millert + + * check.c: moved a lot of the shadow passwd crap to sudo_getpwuid() + +1995-11-20 22:01 millert + + * sudo.c: now uses sudo_pw_ent + +1995-11-20 21:50 millert + + * testsudoers.c: now uses sudo_pw_ent + +1995-11-20 21:40 millert + + * visudo.c: now sets sudo_pw_ent + +1995-11-20 21:28 millert + + * getspwuid.c: Initial revision + +1995-11-20 21:28 millert + + * tgetpass.c: moved dce stuff into compat.h + +1995-11-20 21:27 millert + + * sudo.h, logging.c: now uses sudo_pw_ent + +1995-11-20 21:27 millert + + * Makefile.in: added sudo_getpwuid.c + +1995-11-20 21:25 millert + + * compat.h: added dce support + +1995-11-20 21:13 millert + + * parse.yacc: now uses sudo_pw_ent + +1995-11-20 14:40 millert + + * check.c: fixed exempt_group stuff for OS's that don't put base + gid in group vector + +1995-11-20 01:39 millert + + * check.c: S/Key support now works with sunos4 shadow passwords + +1995-11-19 22:31 millert + + * Makefile.in: fixed clean rule + +1995-11-19 22:31 millert + + * config.h.in, configure.in: added DCE support + +1995-11-19 22:30 millert + + * tgetpass.c: DCE & KERB support + +1995-11-19 22:30 millert + + * check.c: first stab at dce support + +1995-11-19 22:24 millert + + * dce_pwent.c: now smells like sudo + +1995-11-19 22:11 millert + + * dce_pwent.c: Initial revision + +1995-11-19 21:36 millert + + * check.c: skey'd sudo now works w/ normal password as well + +1995-11-19 18:37 millert + + * Makefile.in, OPTIONS, check.c, compat.h, config.h.in, + find_path.c, getwd.c, goodpath.c, ins_2001.h, ins_classic.h, + ins_csops.h, ins_goons.h, insults.h, interfaces.c, logging.c, + options.h, parse.c, parse.lex, parse.yacc, pathnames.h.in, + putenv.c, strdup.c, sudo.c, sudo.h, sudo_setenv.c, testsudoers.c, + tgetpass.c, utime.c, version.h, visudo.c: updated version number + +1995-11-19 18:32 millert + + * README: updated to reflect version change + +1995-11-19 18:27 millert + + * configure.in: --with options now line up ++version + +1995-11-19 18:26 millert + + * sudo.h: removed unecesary S/Key stuff + +1995-11-19 18:25 millert + + * configure.in: fixed S/Key support + +1995-11-19 18:24 millert + + * Makefile.in: -I stuff now goes in CPPFLAGS + +1995-11-19 18:23 millert + + * check.c: fixed SKey support + +1995-11-19 15:23 millert + + * README: updated version + +1995-11-19 13:59 millert + + * OPTIONS: fixed description of EXEMPTGROUP + +1995-11-19 10:47 millert + + * sudo.c: more people use _RLD_ than just alphas... + +1995-11-18 21:35 millert + + * Makefile.in: replaced $man_prefix with $mandir + +1995-11-18 21:30 millert + + * configure.in: fixed a typo + +1995-11-18 21:28 millert + + * Makefile.in: now use more GNU'ish dir names + +1995-11-18 21:27 millert + + * configure.in: now set *dir correctly (can override from command + line) + +1995-11-18 19:17 millert + + * sudo.c: now deal with situations where we getwd() fails + +1995-11-17 00:37 millert + + * Makefile.in: added etc_dir, bin_dir, sbin_dir + +1995-11-17 00:37 millert + + * configure.in: added sbin_dir + +1995-11-16 21:28 millert + + * Makefile.in: now ship a flex-generated lex.yy.c + +1995-11-16 21:09 millert + + * Makefile.in: now sets _PATH_SUDO_SUDOERS, _PATH_SUDO_STMP, + SUDOERS_OWNER + +1995-11-16 21:06 millert + + * pathnames.h.in: _PATH_SUDO_SUDOERS & _PATH_SUDO_STMP are now + overridden via Makefile + +1995-11-16 21:05 millert + + * options.h: no more error for redefining SUDOERS_OWNER + +1995-11-16 21:05 millert + + * OPTIONS: expanded SUDOERS_OWNER section + +1995-11-16 03:05 millert + + * visudo.c: now warn if chown(2) failed + +1995-11-16 02:55 millert + + * logging.c: better default warning for NO_SUDOERS_FILE + +1995-11-16 02:54 millert + + * sudo.c: added missing set_perms() no more cryptic message if the + sudoers file is zero length, now just give a parse error + +1995-11-16 02:42 millert + + * logging.c: better diagnostics if NO_SUDOERS_FILE + +1995-11-16 02:41 millert + + * sudo.c: check_sudoers() now catches sudoers files that are not + readable (but are stat'able). + +1995-11-13 01:12 millert + + * configure.in: now add -D__STDC__ for convex cc (not gcc) + +1995-11-13 00:52 millert + + * configure.in: MAN_PREFIX -> man_prefix now sets prefix and + exec_prefix + +1995-11-13 00:52 millert + + * Makefile.in: now uses exec_prefix & prefix from configure + +1995-11-13 00:16 millert + + * find_path.c, getwd.c, goodpath.c, interfaces.c, logging.c, + parse.c, parse.lex, parse.yacc, sudo.c, sudo.h, sudo_setenv.c, + tgetpass.c, utime.c, visudo.c: options.h is now <> instead of "" + so shadow build trees can have a custom copy of options.h + +1995-11-13 00:15 millert + + * check.c: user_is_exempt() is no longer a hack, it now uses + getgrnam() + +1995-11-12 23:56 millert + + * options.h: EXEMPTGROUP is now "sudo" + +1995-11-12 22:25 millert + + * configure.in: MAN_POSTINSTALL now contains a leading space + +1995-11-12 22:25 millert + + * Makefile.in: removed leading tab if @MAN_POSTINSTALL@ not defined + now removes testsudoers in clean: + +1995-11-12 22:24 millert + + * tgetpass.c: includes pwd.h to get _PASSWD_LEN definition + +1995-10-30 15:51 millert + + * sudo.c: unset the KRB_CONF envariable if using kerberos so we + don't get spoofed into using a bogus server + +1995-09-29 17:50 millert + + * parse.yacc: now explicately initialize match[] tp be FALSE + +1995-09-23 16:48 millert + + * sudo.c: removed unused variable now passes -Wall + +1995-09-23 16:48 millert + + * parse.yacc: yyerror and dumpaliases are now void's now passes + -Wall + +1995-09-23 16:48 millert + + * parse.lex: added prototype for yyerror + +1995-09-23 16:47 millert + + * interfaces.c: rmeoved unused cruft now passes -Wall + +1995-09-23 16:47 millert + + * check.c, logging.c, parse.c: now passes -Wall + +1995-09-23 16:46 millert + + * Makefile.in: fixed headers that moved to emul dir + +1995-09-23 12:05 millert + + * logging.c: fixed deref of nil pointer if no args + +1995-09-15 19:18 millert + + * OPTIONS: added a caveat to FQDN section + +1995-09-13 19:48 millert + + * Makefile.in: more $srcdir support for install targets + +1995-09-13 17:17 millert + + * find_path.c, interfaces.c, parse.c, parse.lex, parse.yacc, + putenv.c, strdup.c, sudo.c, sudo_setenv.c, testsudoers.c, + visudo.c: don't include malloc.h if we include stdlib.h + +1995-09-12 21:44 millert + + * parse.yacc: local search.h now lives in emul + +1995-09-12 21:41 millert + + * lsearch.c: local search.h now lives in emul + +1995-09-12 21:41 millert + + * check.c, utime.c: local utime.h now lives in emul dir + +1995-09-12 21:38 millert + + * Makefile.in: added support for building in other than the + sourcedir + +1995-09-10 14:01 millert + + * OPTIONS: annotated CSOPS_INSULTS option + +1995-09-10 13:56 millert + + * TROUBLESHOOTING: updated shadow passwords blurb + +1995-09-09 21:00 millert + + * sudo.c: if SHELL_IF_NO_ARGS is set, "sudo -- foo" now runs a + shell and passes along foo as the arguments + +1995-09-09 18:52 millert + + * parse.lex: collapsed pathname and dir sections into one -- its + now less expensive + +1995-09-09 18:34 millert + + * parse.lex: fixed spacing quoting [,:\\=] now works correctly + append() and fill() now take args to make the above work + +1995-09-08 20:51 millert + + * sudo.c: fixed a typo that caused commands with no tty on fd 0 but + a tty on fd 1 to erroneously have "none" as their tty + +1995-09-04 15:35 millert + + * check.c: timestampfile is now a global static removed decl of + timestampfile in remove_timestamp since we can just use the + global one + +1995-09-04 15:28 millert + + * check.c: created touch() to update timestamps added + USE_TTY_TICKETS support (bit of a kludge) + +1995-09-04 15:28 millert + + * compat.h: added _S_IFDIR and S_ISDIR + +1995-09-04 15:22 millert + + * OPTIONS, options.h: added USE_TTY_TICKETS + +1995-09-04 00:38 millert + + * parse.yacc: removed const from casts for lsearch() & lfind() to + placate irix 4.x C compiler + +1995-09-03 14:12 millert + + * sudo.c: now only strip '/dev/' off of a tty if it starts with + '/dev/' + +1995-09-03 14:12 millert + + * pathnames.h.in: added _PATH_DEV + +1995-09-03 14:11 millert + + * configure.in: AC_HAVE_HEADERS -> AC_CHECK_HEADERS now check for + tcgetattr only if have termios.h + +1995-09-03 14:09 millert + + * tgetpass.c: fixed incorrect #ifdef termio uses "unsigned short" + not int for c_?flag + +1995-09-03 13:19 millert + + * parse.lex, parse.yacc: fixed a spelling error + +1995-09-03 13:17 millert + + * Makefile.in: fixed typo + +1995-09-02 12:55 millert + + * Makefile.in: fixed a comment + +1995-09-02 12:54 millert + + * parse.yacc: added dotcat() to cat 2 strings w/ a dot effeciently + now that we dynamically allocate strings they need to be free()'d + +1995-09-02 12:46 millert + + * parse.lex: dynamically allocates space for strings + +1995-09-02 12:34 millert + + * sudo.h: no more MAXCOMMANDLENGTH + +1995-09-01 22:25 millert + + * sudo.h: added decl of tty + +1995-09-01 22:25 millert + + * logging.c, sudo.c: moved tty stuff into sudo.c + +1995-09-01 14:18 millert + + * parse.c: fixed a logic bug. Was denying a command if user gave + command line args but there were none in the sudoers file which + is wrong. + +1995-09-01 01:18 millert + + * sudo.h: MAXCOMMMANDLEN dropped down to 1K + +1995-09-01 01:13 millert + + * parse.lex: return foo; -> return(foo); + +1995-09-01 01:03 millert + + * parse.yacc: fixed netgr_matches() prototype + +1995-09-01 01:02 millert + + * parse.lex: added support for escaping "termination" characters + +1995-09-01 00:55 millert + + * parse.c: buf is now of size MAXPATHLEN+1 since it never holds + command args + +1995-09-01 00:50 millert + + * sudo.c: fixed comments + +1995-09-01 00:49 millert + + * goodpath.c: fixed negation problem (doh!) + +1995-09-01 00:25 millert + + * parse.yacc: fixed 2nd parameter to lfind() + +1995-09-01 00:24 millert + + * parse.lex: now do bounds checking in fill() and append() + +1995-09-01 00:23 millert + + * sudo.c: include netdb.h as we should added a missing void cast + added SHELL_IF_NO_ARGS support now use realloc() properly. would + fail if realloc actually moved the string instead of shrinking it + +1995-09-01 00:17 millert + + * sample.sudoers: updated with examples of new features + +1995-09-01 00:05 millert + + * goodpath.c: now set errno to EACCES if not a regular file or not + executable + +1995-09-01 00:04 millert + + * find_path.c: if given a fully-qualified or relative path we now + check it with sudo_goodpath() and error out with the appropriate + error message if the file does not exist or is not executable + +1995-09-01 00:03 millert + + * lsearch.c, emul/search.h: now use correct args for lfind + +1995-09-01 00:03 millert + + * logging.c: added a comment + +1995-08-31 23:52 millert + + * insults.h: added in CSOps insults + +1995-08-31 23:51 millert + + * ins_csops.h: Initial revision + +1995-08-31 23:35 millert + + * tgetpass.c: added RCS id + +1995-08-31 22:56 millert + + * sudo.h: increased MAXCOMMANDLENGTH to 8k HAVE_GETCWD -> + HAVE_GETWD + +1995-08-31 22:55 millert + + * OPTIONS: added CLASSIC_INSULTS, CSOPS_INSULTS, SHELL_IF_NO_ARGS + +1995-08-31 22:54 millert + + * sudo.c: fixed -k load_interfaces() now gets called if FQDN is set + -p now works with -s + +1995-08-31 22:54 millert + + * parse.c: don't try to stat() "pseudo commands" like "validate" + +1995-08-31 22:53 millert + + * options.h: added CLASSIC_INSULTS added CSOPS_INSULTS added + SHELL_IF_NO_ARGS + +1995-08-31 22:53 millert + + * configure.in: added SecurID support added other insults to + --with-csops + +1995-08-31 22:52 millert + + * config.h.in: added HAVE_SECURID + +1995-08-31 22:52 millert + + * Makefile.in: added clobber target added ins_csops.h now gets + CFLAGS from configure + +1995-08-31 22:46 millert + + * aclocal.m4: relaxed SUDO_FULL_VOID + +1995-08-31 22:44 millert + + * visudo.c: function comment blocks are now in same style as rest + of code + +1995-08-31 22:44 millert + + * testsudoers.c: added support for command line args in + /etc/sudoers + +1995-08-31 22:43 millert + + * sudoers.man: updated to have command args in the sudoers file + +1995-08-31 22:42 millert + + * sudo.man: added -s and -- flags added SHELL to ENVIRONMENT + VARIABLES section + +1995-08-19 19:32 millert + + * parse.yacc: PATH renamed to COMMAND + +1995-08-19 19:31 millert + + * parse.lex: it is now a parse error for directories to have args + attached to them + +1995-08-19 19:30 millert + + * logging.c: now say command args if telling user to buzz off + +1995-08-19 19:30 millert + + * sudo.c: -s no longer indicates end of args sped up loading on + cmnd_args in load_cmnd() + +1995-08-19 19:29 millert + + * parse.c: removed an unreachable statement + +1995-08-19 17:53 millert + + * parse.lex: made more efficient by pulling out the terminators + when in GOTCMND state and making them their own rule + +1995-08-14 00:07 millert + + * sudo.h: removed MAXLOGLEN since it is no longer used + +1995-08-14 00:07 millert + + * parse.lex: now allows command args + +1995-08-14 00:06 millert + + * parse.c: now groks command arguments + +1995-08-13 23:39 millert + + * logging.c: now sets tty correctly when piped input + +1995-08-13 23:35 millert + + * sudo.c: fixed loading of cmnd_args (was including command name + too) + +1995-08-13 23:34 millert + + * logging.c: fixed a core dump due to incorrect if construct + +1995-08-13 00:33 millert + + * configure.in: only add -lsun is irix < 5 don't look for -lnsl or + -lsocket if irix + +1995-08-13 00:33 millert + + * aclocal.m4: fixed check for ISC + +1995-08-13 00:32 millert + + * sudo.c: now sets cmnd_args used by log_error() and that will be + used by the parse to check against command args + +1995-08-13 00:32 millert + + * sudo.h: added cmnd_args + +1995-08-13 00:31 millert + + * logging.c: now dynamically allocate logline since we can guess at + its size + +1995-08-05 13:52 millert + + * logging.c: cleaned up a bunch of unnecesary #ifdef's eliminated a + buffer remove "register" since the compiler knows more than I do + now do a "basename" of the tty + +1995-07-31 18:20 millert + + * configure.in: ++version + +1995-07-30 22:37 millert + + * sudo.h: added shell extern changed MODE_* to be bit masks to + allow for several options together + +1995-07-30 22:36 millert + + * sudo.c: added -s (shell) option made MODE_* masks so we can do + bitwise & and | to see if multiple flags are set. + +1995-07-30 22:01 millert + + * check.c: added securid support + +1995-07-30 14:38 millert + + * logging.c: removed a bunch of unnecesary strncpy()'s and replaced + with strcat() + +1995-07-29 17:17 millert + + * Makefile.in, version.h: ++version + +1995-07-27 06:52 millert + + * parse.yacc: fixed free() of an uninitialized pointer (yuck) + +1995-07-26 22:00 millert + + * testsudoers.c: added netgr_matches + +1995-07-26 21:29 millert + + * parse.c: cleaned up netgr_matches + +1995-07-26 00:26 millert + + * RUNSON: updated for 1.3.4 + +1995-07-24 21:51 millert + + * Makefile.in: now installs sudoers.man -- really should clean this + up though. + +1995-07-24 21:18 millert + + * Makefile.in: added sudoers.cat and sudoers.man + +1995-07-24 21:15 millert + + * sudo.man: pulled out stuff on the sudoers file format into a + separate man page + +1995-07-24 21:14 millert + + * sudoers.man: Initial revision + +1995-07-24 21:04 millert + + * HISTORY: fixed up my email address + +1995-07-24 20:03 millert + + * configure.in: added checks for innetgr and getdomainname + +1995-07-24 20:02 millert + + * visudo.c: added dummy netgr_matches function + +1995-07-24 20:01 millert + + * parse.c: added netgr_matches + +1995-07-24 20:01 millert + + * parse.lex, parse.yacc: added NETGROUP support + +1995-07-24 20:01 millert + + * config.h.in: added HAVE_INNETGR & HAVE_GETDOMAINNAME + +1995-07-24 18:07 millert + + * sudo.c: rewrote clean_env() that has rm_env() builtin + +1995-07-23 19:58 millert + + * check.c: now cast uid to long in sprintf + +1995-07-23 19:58 millert + + * OPTIONS: added _INSULTS suffix to HAL & GOONS end + +1995-07-23 19:57 millert + + * options.h: added _INSULTS suffix to HAL & GOONS + +1995-07-23 19:35 millert + + * ins_2001.h, ins_classic.h, ins_goons.h, insults.h: converted to + new scheme of insult "unions" end + +1995-07-23 17:48 millert + + * sudo.c: now uses MAX_UID_T_LEN + +1995-07-23 17:48 millert + + * configure.in: added SUDO_UID_T_LEN !l + +1995-07-23 17:48 millert + + * config.h.in: added MAX_UID_T_LEN + +1995-07-23 17:47 millert + + * check.c: now use MAX_UID_T_LEN + +1995-07-23 17:47 millert + + * aclocal.m4: added check for max len of uid_t fixed sco vs. isc + check + +1995-07-19 19:05 millert + + * configure.in: corrected version + +1995-07-19 17:29 millert + + * configure.in: added sco support + +1995-07-19 17:29 millert + + * aclocal.m4: hack to check for sco + +1995-07-18 21:27 millert + + * interfaces.c: removed #include since it was hosing + some OS's + +1995-07-18 13:35 millert + + * find_path.c: fixed prreadlink() prototype + +1995-07-17 23:54 millert + + * check.c: added parens in #if's + +1995-07-17 23:53 millert + + * configure.in: added SPW_ prefix + +1995-07-17 23:20 millert + + * sudo.h: moved SPW_* to config.h.in + +1995-07-17 23:19 millert + + * sudo.c: added a set of parens + +1995-07-17 23:19 millert + + * config.h.in: added SPW_* + +1995-07-17 22:50 millert + + * sudo.h: added SPW_* reordered error codes + +1995-07-17 22:49 millert + + * check.c: moved SPW_* to sudo.h + +1995-07-17 14:29 millert + + * logging.c: GLOBAL_NO_AUTH_ENT -> GLOBAL_NO_SPW_ENT + +1995-07-17 14:29 millert + + * configure.in: AUTH -> SECUREWARE + +1995-07-17 14:29 millert + + * check.c, sudo.c: SPW_AUTH -> SPW_SECUREWARE + +1995-07-17 00:22 millert + + * check.c: now uses SHADOW_TYPE to make shadow pw support more + readable and modular. It's a start... + +1995-07-17 00:21 millert + + * configure.in: added autodetection of shadow passwords + +1995-07-17 00:20 millert + + * sudo.c: now uses SHADOW_TYPE define + +1995-07-17 00:19 millert + + * config.h.in: added SHADOW_TYPE which replaces SUNOS4 & __svr4__ + defines + +1995-07-17 00:19 millert + + * aclocal.m4: added SUDO_CHECK_SHADOW + +1995-07-12 17:09 millert + + * configure.in: define SVR4 for ISC define BROKEN_SYSLOG for hpux + took out test for memmove() since we dno longer use it... + +1995-07-12 17:08 millert + + * CHANGES: updated + +1995-07-12 17:05 millert + + * logging.c: added BROKEN_SYSLOG support + +1995-07-12 17:05 millert + + * config.h.in: added BROKEN_SYSLOG + +1995-07-12 17:04 millert + + * check.c: now only bitch it timestamp > time_now + 2 * timeout to + allow for a machine udpating its time from a server + +1995-07-12 17:04 millert + + * sudo.man: added 2 security notes updated Nieusma's email addr + +1995-07-12 14:18 millert + + * lsearch.c: changed a memmove() to memcpy() since we don't have to + worry about overlapping segments. + +1995-07-11 15:41 millert + + * interfaces.c: cleanup up the loop when interfaces are groped in + so that it is readable + +1995-07-11 14:52 millert + + * Makefile.in, version.h: ++version + +1995-07-09 18:17 millert + + * CHANGES: annotated 124-126 + +1995-07-07 16:06 millert + + * check.c: fixed permissions check on /tmp/.odus + +1995-07-06 19:35 millert + + * check.c: fixed some comments + +1995-07-06 14:49 millert + + * check.c: now checks owner & mode of timedir also checks for bogus + dates on timestamp file + +1995-07-06 14:49 millert + + * OPTIONS: updated TIMEOUT info + +1995-07-06 14:48 millert + + * logging.c, sudo.h: added BAD_STAMPDIR and BAD_STAMPFILE + +1995-07-06 14:47 millert + + * compat.h: added definition of S_IRWXU + +1995-07-06 14:47 millert + + * CHANGES: updated + +1995-07-03 14:16 millert + + * interfaces.c: added #ifdef to make it compile on strange arches + +1995-07-02 18:13 millert + + * aclocal.m4: fixed check for fulkl void impl. + +1995-07-02 09:56 millert + + * check.c: added mssing "static" + +1995-07-01 20:41 millert + + * insults.h: replaced #elif with #else #if constructs for ancient C + compilers + +1995-07-01 20:18 millert + + * INSTALL: updated irix c2 & kerb5 info + +1995-07-01 20:15 millert + + * configure.in: added shadow pw support for irix + +1995-07-01 16:07 millert + + * CHANGES: last changes for sudo 1.3.3 + +1995-07-01 16:07 millert + + * TODO, BUGS: updated + +1995-07-01 16:04 millert + + * configure.in: now calls SUDO_SOCK_SA_LEN + +1995-07-01 16:04 millert + + * config.h.in: added HAVE_SA_LEN + +1995-07-01 16:04 millert + + * aclocal.m4: added SUDO_SOCK_SA_LEN + +1995-07-01 15:49 millert + + * interfaces.c: now works with ip implementations that use sa_len + in sockaddr + +1995-07-01 14:26 millert + + * INSTALL: added note about buggy AIX compiler + +1995-07-01 14:24 millert + + * interfaces.c: now include sys/time.h for AIX + +1995-06-27 22:35 millert + + * Makefile.in: getcwd -> getwd + +1995-06-27 21:28 millert + + * interfaces.c: now works for ISC and others. yay. + +1995-06-26 14:24 millert + + * Makefile.in, version.h: version++ + +1995-06-22 20:26 millert + + * aclocal.m4: fixed test for full void impl + +1995-06-22 20:25 millert + + * sudo.c: now check to see that st_dev is non-zero before assuming + that we are being spoofed + +1995-06-20 16:56 millert + + * aclocal.m4, configure.in: SUDO_FUNC_UTIME_NULL -> + AC_FUNC_UTIME_NULL + +1995-06-19 16:32 millert + + * aclocal.m4: fixed include file order for SUDO_FUNC_UTIME_POSIX + +1995-06-19 16:10 millert + + * logging.c: added cast for ttyname() + +1995-06-19 15:23 millert + + * configure.in: fixed typo + +1995-06-19 15:19 millert + + * check.c: now deal correctly with all known variation of utime() + -- yippe + +1995-06-19 15:19 millert + + * configure.in: added SUDO_FUNC_UTIME_POSIX + +1995-06-19 15:19 millert + + * aclocal.m4: added SUDO_FUNC_UTIME_NULL and SUDO_FUNC_UTIME_POSIX + +1995-06-19 15:14 millert + + * config.h.in: added HAVE_UTIME_POSIX + +1995-06-19 13:38 millert + + * check.c: fixed a typo + +1995-06-19 13:29 millert + + * check.c: no longer assume !HAVE_UTIME_NULL means old BSD utime() + +1995-06-19 13:20 millert + + * check.c: fixed fascist C compiler warning + +1995-06-18 23:14 millert + + * interfaces.c: now set strioctl.ic_timout in STRSET() now + initialize num_interfaces to 0 (just to be anal) + +1995-06-18 18:06 millert + + * sudo.h: increaed MAXLOGLEN by MAXPATHLEN to account for ttyname + +1995-06-18 18:05 millert + + * logging.c: added tty logging + +1995-06-18 16:04 millert + + * interfaces.c: reworked the ISC code + +1995-06-18 15:27 millert + + * Makefile.in, version.h: updated version + +1995-06-18 15:24 millert + + * check.c: now expect old-style utime(3) if utime() can't take NULL + as an arg + +1995-06-18 15:08 millert + + * configure.in: added check for utime.h + +1995-06-18 15:08 millert + + * config.h.in: added HAVE_UTIME_H + +1995-06-18 14:48 millert + + * Makefile.in: added CPPFLAGS STATIC_FLAGS -> LDFLAGS + +1995-06-18 13:58 millert + + * configure.in: now search for kerb libs and includes + +1995-06-18 13:03 millert + + * check.c: added support for utime(2)'s that can't take a NULL + parameter + +1995-06-18 13:03 millert + + * utime.c: moved HAVE_UTIME_NULL stuff to update_timestamp() where + t belongs + +1995-06-17 20:46 millert + + * configure.in: added utime(s) stuff + +1995-06-17 20:46 millert + + * check.c: now use utime() + +1995-06-17 20:46 millert + + * config.h.in: added HAVE_UTIME and HAVE_UTIME_NULL + +1995-06-17 19:12 millert + + * utime.c: now use HAVE_UTIME_NULL + +1995-06-17 19:02 millert + + * utime.c, emul/utime.h: Initial revision + +1995-06-17 18:24 millert + + * check.c: need to setuid(0) to make kerb4 stuff work. + +1995-06-17 18:14 millert + + * tgetpass.c: no more special case for kerberos + +1995-06-17 18:13 millert + + * config.h.in: took out setreuid and setresuid stuff added kerb5 + stuff (use kerb4 emulation) + +1995-06-17 18:13 millert + + * compat.h: no longer need setreuid() emulation now set _PASSWD_LEN + to 128 if kerberos + +1995-06-17 18:12 millert + + * check.c: now use private ticket file for kerberos support to + avoid trouncing on system one + +1995-06-15 00:48 millert + + * sudo.h: added SPOOF_ATTEMPT & cmnd_st + +1995-06-15 00:47 millert + + * sudo.c: added anti-spoofing support + +1995-06-15 00:47 millert + + * parse.c: now use global cmnd_st + +1995-06-15 00:47 millert + + * logging.c: added SPOOF_ATTEMPT suypport + +1995-06-14 23:41 millert + + * testsudoers.c, visudo.c: added void casts where appropriate + +1995-06-14 23:40 millert + + * parse.yacc: fixed up spacing and added void casts where + appropriate + +1995-06-14 23:27 millert + + * sudo.c: fixed problem with "-p prompt" but no args + +1995-06-14 04:43 millert + + * sudo.man: added BUGS and annotated -l description + +1995-06-14 04:43 millert + + * sudo.h: validate() now takes a flag + +1995-06-14 04:43 millert + + * sudo.c: validate() now takes a flag added -l + +1995-06-14 04:42 millert + + * parse.yacc: added support for -l + +1995-06-14 04:41 millert + + * parse.c: validate() now takes a flag that says whether or not to + check the command + +1995-06-07 21:36 millert + + * logging.c: now deals with Argv == 1 + +1995-06-07 21:34 millert + + * sudo.man: added -p option + +1995-06-07 21:27 millert + + * sudo.c: added prompt support reworked parse_args() + +1995-06-07 20:49 millert + + * sudo.h: added prompt + +1995-06-07 20:49 millert + + * options.h: added PASSPROMPT + +1995-06-07 20:48 millert + + * check.c: now use BUFSIZ as length of kerb password added kpass so + pass is always a char * now use prompt global when asking for a + password + +1995-06-07 20:47 millert + + * tgetpass.c: now use BUFSIZ as _PASSWD_LEN if using kerberos + +1995-06-07 20:43 millert + + * OPTIONS: added PASSPROMPT + +1995-06-07 01:44 millert + + * configure.in: only look for -lufc or -lcrypt if crypt() not in + libc + +1995-06-07 01:43 millert + + * check.c: don't exit on kerb error, just warn if k_errno == + KDC_PR_UNKNOWN (unknown user) silently fail + +1995-06-06 22:44 millert + + * INSTALL: added kerb4 note + +1995-06-06 22:43 millert + + * tgetpass.c: HAVE_KERBEROS -> HAVE_KERB4 + +1995-06-06 22:41 millert + + * check.c: removed debugging printf + +1995-06-06 22:33 millert + + * configure.in: KERBEROS -> KERB4 added checks for setreuid & + setresuid + +1995-06-06 22:32 millert + + * config.h.in: HAVE_KERBEROS -> HAVE_KERB4 added HAVE_SETREUID and + HAVE_SETRESUID + +1995-06-06 22:32 millert + + * compat.h: added deif of UID_NO_CHANGE & GID_NO_CHANGE added + setreuid emulation with setresuid if applic + +1995-06-06 22:31 millert + + * check.c: HAVE_KERBEROS -> HAVE_KERB4 now only do the stupid + chown() hack if no setreuid() or a broken one + +1995-06-05 23:44 millert + + * config.h.in: added HAVE_KERBEROS + +1995-06-05 23:43 millert + + * tgetpass.c: added KERBEROS support (long passwords) + +1995-06-05 23:42 millert + + * check.c, configure.in: added kerberos support + +1995-06-03 19:36 millert + + * sudo.h: added MODE_BACKGROUND + +1995-06-03 19:36 millert + + * sudo.man: escaped dashes added -b option + +1995-06-03 19:34 millert + + * sudo.c: added -b option + +1995-06-03 18:52 millert + + * check.c: added crypt() for osf/1 3.x enhanced secuiry + +1995-06-03 18:18 millert + + * configure.in: now check for -lcrypt + +1995-06-03 18:00 millert + + * interfaces.c: added ENXIO like EADDRNOTAVAIL + +1995-05-07 23:14 millert + + * configure.in: now emulate getwd(), not getcwd() + +1995-05-07 23:13 millert + + * sudo.c: getcwd() -> getwd() + +1995-05-07 23:12 millert + + * getwd.c: getcwd -> getwd + +1995-05-02 01:34 millert + + * ins_2001.h, ins_classic.h, ins_goons.h: Initial revision + +1995-05-02 01:34 millert + + * insults.h: broke out insults into separate include files + +1995-05-02 01:32 millert + + * options.h, OPTIONS: added GOONS + +1995-05-02 01:32 millert + + * Makefile.in: added ins_2001.h ins_classic.h ins_goons.h + +1995-05-01 23:34 millert + + * Makefile.in, version.h: ++version + +1995-05-01 23:34 millert + + * visudo.c: moved signal handler setup to setup_signals() + +1995-05-01 23:33 millert + + * sudo.h: added load_interfaces() + +1995-05-01 23:33 millert + + * sudo.c: moved load_interfaces to interfaces.c + +1995-05-01 23:33 millert + + * parse.yacc: added clearaliases + +1995-05-01 23:33 millert + + * OPTIONS, options.h: added FAST_MATCH + +1995-05-01 23:32 millert + + * parse.lex: now uses clearaliases variable + +1995-05-01 23:31 millert + + * interfaces.c: Initial revision + +1995-05-01 23:31 millert + + * Makefile.in: added interfaces.[co] + +1995-05-01 23:30 millert + + * testsudoers.c: now uses ip addrs and netmasks via + load_interfaces() + +1995-05-01 22:47 millert + + * sudo.c: now remove IFS instead of setting to "sane" value + +1995-05-01 16:30 millert + + * parse.c: added FAST_MATCH + +1995-04-29 20:19 millert + + * Makefile.in: sudo_goodpath.c-> goodpath.c + +1995-04-29 20:15 millert + + * sudo.c: added Andy's new ISC changes + +1995-04-14 14:06 millert + + * OPTIONS: added a sentence to SECURE_PATH info + +1995-04-14 13:57 millert + + * BUGS: added one + +1995-04-14 13:54 millert + + * RUNSON, CHANGES: updated + +1995-04-13 17:04 millert + + * RUNSON: updated for beta3 + +1995-04-13 14:32 millert + + * Makefile.in, version.h: ++version + +1995-04-13 13:56 millert + + * aclocal.m4: sendmail is now looked for in /usr/ucblib + +1995-04-13 13:54 millert + + * sudo.c: fixed indentation + +1995-04-13 13:35 millert + + * aclocal.m4: fixed a typo + +1995-04-13 13:19 millert + + * sudo.c: updated ISC mods + +1995-04-13 13:19 millert + + * configure.in: added unixware case + +1995-04-13 13:19 millert + + * check.c: user_is_exempt is no longer hidden + +1995-04-13 13:19 millert + + * RUNSON: updated + +1995-04-13 13:19 millert + + * aclocal.m4: isc and riscos changes + +1995-04-13 13:18 millert + + * OPTIONS: added NOTE about new interaction of EXEMPTGROUP and + SECURE_PATH + +1995-04-13 13:18 millert + + * Makefile.in: fixed a typo and added testsudoers stuff + +1995-04-13 12:34 millert + + * testsudoers.c: Initial revision + +1995-04-12 19:31 millert + + * parse.yacc: applied fixed patch from Chris + +1995-04-11 14:30 millert + + * Makefile.in: fixed a typo + +1995-04-11 14:14 millert + + * parse.yacc: added a set of braces for bison + +1995-04-11 14:01 millert + + * parse.yacc: merged in Chris' changes to dekludge the parser. + +1995-04-11 00:38 millert + + * logging.c: send_mail() was calling find_path() which is wrong + since find_path() stores cmnd in a static var. Anyhow, it + doesn't make much sense since MAILER should always be fully + qualified + +1995-04-10 19:51 millert + + * sample.sudoers: added User_Alias stuff + +1995-04-10 19:50 millert + + * aclocal.m4: SUDO_NEXT now looks for + /usr/lib/NextStep/software_version + +1995-04-10 19:50 millert + + * RUNSON: added DEC UNIX 3.0 w/ gcc + +1995-04-10 19:49 millert + + * visudo.c: Exit was being used in places where exit should be used + +1995-04-10 19:44 millert + + * sudoers: added "User alias specification" + +1995-04-10 18:04 millert + + * parse.yacc: fixed probs caused by making nslots and naliases a + size_t + +1995-04-10 15:09 millert + + * RUNSON: added KSR, upped rev to 1.3.1b2 + +1995-04-10 15:07 millert + + * logging.c, parse.yacc: 1024 -> BUFSIZ + +1995-04-10 15:05 millert + + * parse.yacc: void * -> VOID * naliases and nslots are now size_t + to appease lsearch on 64-bit machines + +1995-04-09 19:30 millert + + * TODO: did a bunch of things and added a bunch :-) + +1995-04-09 19:30 millert + + * PORTING: updated + +1995-04-09 19:24 millert + + * visudo.man: closer to BSD manpage style + +1995-04-09 19:15 millert + + * sudo.man: closer to standard BSD man format + +1995-04-09 18:58 millert + + * compat.h, config.h.in, insults.h, options.h, pathnames.h.in, + sudo.h, version.h, emul/search.h: added RCS id + +1995-04-09 17:35 millert + + * sudo.h: removed crufty #defines that are no longer used + +1995-04-09 17:13 millert + + * BUGS: fixed a bug + +1995-04-09 17:12 millert + + * sudo.man: updated based on sudo changes + +1995-04-09 17:11 millert + + * parse.yacc: now allow ALL keyword in User_Aliases now allow ALL + keyword as well as a NAME or ALIAS + +1995-04-09 17:11 millert + + * CHANGES: updated + +1995-04-09 17:04 millert + + * sudo.c: now sets SUDO_COMMAND and SUDO_GID envariables. + +1995-04-09 15:24 millert + + * aclocal.m4: fixed bug with full void impl check + +1995-04-08 23:11 millert + + * parse.yacc: fixed User_Alias supoprt + +1995-04-08 22:27 millert + + * parse.yacc: added stubs for User_Alias support + +1995-04-08 22:27 millert + + * sudo.c: now sets removes # bogus interfaces from num_interfaces + +1995-04-08 22:26 millert + + * parse.lex: added User_Alias support + +1995-04-07 21:10 millert + + * Makefile.in: removed extraneous TODO + +1995-04-07 19:48 millert + + * visudo.c: ntwk_matches -> addr_matches + +1995-04-07 15:38 millert + + * parse.yacc: ntwk_matches -> addr_matches + +1995-04-07 15:37 millert + + * parse.c: ntwk_matches -> addr_matches now use inet_addr() not + inet_network() (which expects octet boundaries) fixes for OSF + (sizeof(int) != sizeof(long)) + +1995-04-07 15:08 millert + + * sudo.c: took out debugging info + +1995-04-06 23:45 millert + + * aclocal.m4: OS was being set to unknown before non-uname based + host checks. This caused no checks to happen since $OS was not + zero-length. + +1995-04-06 23:30 millert + + * sudo.c: fixed loading of interfaces struct still has debugging + info in though + +1995-04-06 22:23 millert + + * parse.c: fixed typo + +1995-04-06 16:17 millert + + * Makefile.in: ++version + +1995-04-06 16:16 millert + + * version.h: ++ + +1995-04-06 16:16 millert + + * visudo.c: removed extraneous extern decl of "top + +1995-04-06 16:14 millert + + * visudo.c: now zeros "top" + +1995-04-06 16:13 millert + + * parse.yacc: removed parser_cleanup (no need for it now) + +1995-04-06 16:13 millert + + * parse.lex: now calls reset_aliases() directly + +1995-04-04 18:21 millert + + * OPTIONS: added a sentence to SECURE_PATH description + +1995-04-04 18:17 millert + + * parse.c: fixed my stupid bug where I used NAMLEN on something I + wanted to just get the name from. argh. + +1995-04-03 16:58 millert + + * lsearch.c: fixed argument order of memmove() that i hosed when + converting from bcopy(). arghh. + +1995-04-03 15:33 millert + + * Makefile.in: finally fixed DISTFILES line + +1995-04-03 15:21 millert + + * Makefile.in: tabs -> spaces + +1995-04-03 15:15 millert + + * Makefile.in: added missing files to DISTFILES + +1995-04-03 14:50 millert + + * Makefile.in: SUPPORTED -> RUNSON + +1995-04-01 03:12 millert + + * TODO: updated + +1995-04-01 01:54 millert + + * RUNSON: updated for pl5b1 release + +1995-04-01 01:53 millert + + * BUGS, TODO: updated + +1995-04-01 01:52 millert + + * check.c: fixed bug where if you hit return at first sudo prompt + it would still log as a failure + +1995-04-01 01:29 millert + + * CHANGES: updated + +1995-04-01 01:25 millert + + * aclocal.m4: better test for bogus void * implementation + +1995-03-31 20:33 millert + + * logging.c: added PASSWORDS_NOT_CORRECT + +1995-03-31 20:32 millert + + * check.c: added PASSWORDS_NOT_CORRECT stuff] + +1995-03-31 20:30 millert + + * sudo.h: added PASSWORDS_NOT_CORRECT + +1995-03-31 19:16 millert + + * tgetpass.c: moved pathnames.h + +1995-03-31 19:16 millert + + * sudo.c: removed some unused vars and fixed up uid2str + +1995-03-31 19:15 millert + + * putenv.c: moved compat.h + +1995-03-31 19:14 millert + + * getcwd.c, getwd.c: added pathnames.h + +1995-03-31 18:18 millert + + * parse.yacc: fixed a typo I introduced in the last checkin :-( + +1995-03-31 18:11 millert + + * parse.lex: can't have #ifdef's where N is defined so just do this + the broken way for AIX + +1995-03-31 18:08 millert + + * parse.yacc: better hack from Chris (but still a hack) + +1995-03-31 18:05 millert + + * parse.lex: stupid hack for broken aix lex + +1995-03-31 17:47 millert + + * tgetpass.c: now includes compat.h  + +1995-03-31 17:27 millert + + * visudo.c: now includes fcntl.h + +1995-03-31 17:27 millert + + * compat.h: added FD_SET and FD_ZERO for 4.2BSD + +1995-03-31 16:12 millert + + * parse.yacc: dirty hack to fix parser bug. i don't really like + this but it works for now... + +1995-03-31 16:12 millert + + * sudo.c: uid2str is now static like the prototype says + +1995-03-29 23:48 millert + + * RUNSON: Initial revision + +1995-03-29 23:47 millert + + * TODO, CHANGES, SUPPORTED, TROUBLESHOOTING: updated + +1995-03-29 23:46 millert + + * sudo.c: check_sudoers now returns an error code and sudo calls + inform_user and log_error based on the return value. + +1995-03-29 23:45 millert + + * logging.c, sudo.h: added entries for new errors + +1995-03-29 23:03 millert + + * parse.c: now set uid to that of SUDOERS_OWNER while parsing + sudoers file + +1995-03-29 22:52 millert + + * Makefile.in: took out testsudoers  + +1995-03-29 22:36 millert + + * sudo.c: now explicately checks that it is setuid root + +1995-03-29 22:28 millert + + * sudo.c: If a user has no passwd entry sudo would segv (writing to + a garbage pointer). Now allocate space before writing :-) + +1995-03-29 22:06 millert + + * configure.in: reordered AC_CHECK_FUNCS + +1995-03-29 22:06 millert + + * config.h.in: fixed memset macro + +1995-03-29 21:47 millert + + * logging.c: bzero -> memset when a parse error is logged the line + number of the error is now logged too + +1995-03-29 21:46 millert + + * tgetpass.c, visudo.c: bzero -> memset + +1995-03-29 21:46 millert + + * INSTALL: added Sunos to blurb about c2 security + +1995-03-29 21:45 millert + + * configure.in: added a SUN4 define for C2 security + +1995-03-29 21:44 millert + + * config.h.in: bcopy -> memmove bzero -> memset + +1995-03-29 21:43 millert + + * lsearch.c: bcopy -> memmove char * -> VOID * + +1995-03-29 21:30 millert + + * check.c: added support for sunos with C2 security + +1995-03-29 21:12 millert + + * OPTIONS, options.h: reordered + +1995-03-29 21:12 millert + + * pathnames.h.in: _PATH_SUDO_LOGFILE now set based on configure + +1995-03-29 21:12 millert + + * configure.in: added SUDO_LOGFILE and SUDO_TYPE_SIZE_T + +1995-03-29 21:12 millert + + * config.h.in: added _SUDO_PATH_LOGFILE + +1995-03-29 21:11 millert + + * aclocal.m4: added SUDO_LOGFILE to find where to put sudo.log + added SUDO_CHECK_TYPE (just AC_CHECK_TYPE but checks unistd.h + too) added SUDO_TYPE_SIZE_T (calls SUDO_CHECK_TYPE) + +1995-03-29 18:17 millert + + * TROUBLESHOOTING: Initial revision + +1995-03-29 17:59 millert + + * sudo.c: now do set_perms(PERM_ROOT) before the getpwuid() in + load_global() to work around a problem is trusted hpux shadow + passwords. yuck. + +1995-03-29 17:41 millert + + * parse.yacc: backed out a change in malloc/realloc + +1995-03-29 17:38 millert + + * parse.yacc: now include stdlib.h + +1995-03-29 17:22 millert + + * visudo.c: now do an freopen() of the stmp file so that yyin will + always point to the same thing. This is important for flex since + we are doing a YY_NEWFILE + +1995-03-29 17:20 millert + + * parse.yacc: replaced yywrap() with parser_cleanup() since + yywrap() needs to be in parse.lex to be able to use YY_NEW_FILE. + sigh. + +1995-03-29 17:18 millert + + * parse.lex: now have a rule that matches anything that doesn't + match an explicite rule. well, you know what i mean (. matches + anything not yet matched). However, this means that there is + input still queued up so we need to do a YY_NEW_FILE; in yywrap. + So, yywrap has moved into parse.lex and it calls parser_cleanup() + which is most of the old yywrap() sigh. + +1995-03-29 17:17 millert + + * SUPPORTED: no longer used + +1995-03-29 16:13 millert + + * getcwd.c, getwd.c: moved compat.h to be the last include file + +1995-03-29 16:11 millert + + * parse.yacc: fixed type of aliascmp() args + +1995-03-29 15:58 millert + + * find_path.c: NULL -> '\0' + +1995-03-29 15:42 millert + + * parse.yacc: added casts to lfind and lsearch args for irix + +1995-03-29 08:20 millert + + * Makefile.in: bsdinstall -> install-sh + +1995-03-29 08:20 millert + + * INSTALL: added info about make realclean + +1995-03-29 08:17 millert + + * Makefile.in: updated VERSION added dependencies for visudo.cat + +1995-03-29 08:17 millert + + * version.h: -> pl5b1 + +1995-03-29 08:16 millert + + * sudo.c: took out -l + +1995-03-29 00:03 millert + + * Makefile.in: now there is a real visudo.man and visudo.cat + +1995-03-28 23:54 millert + + * sudo.man: took out visudo stuff + +1995-03-28 23:54 millert + + * visudo.man: Initial revision + +1995-03-28 23:12 millert + + * parse.c, parse.lex, parse.yacc: updated copyright + +1995-03-28 23:05 millert + + * README: updated for pl5 + +1995-03-28 20:02 millert + + * sudo.man: updated Nieusma & Hieb email addresses + +1995-03-28 19:57 millert + + * INSTALL: updated to include options.h and OPTIONS + +1995-03-28 19:35 millert + + * CHANGES, TODO: updated + +1995-03-28 19:35 millert + + * BUGS: eliminated bug #1 (yay) + +1995-03-28 19:31 millert + + * configure.in: sunos no longer gets linked statically + +1995-03-28 18:58 millert + + * parse.lex: prototype now uses __P() + +1995-03-28 18:49 millert + + * parse.lex: make fill() non-ansi + +1995-03-28 15:26 millert + + * parse.c: made -v (validate) work + +1995-03-28 15:26 millert + + * logging.c: now gives host + +1995-03-28 10:34 millert + + * find_path.c: don't check for execute/statable if fq or relative + path given + +1995-03-28 01:07 millert + + * parse.c: added a cast + +1995-03-28 00:49 millert + + * visudo.c: now include ctype.h for islower and tolower macros + +1995-03-28 00:48 millert + + * goodpath.c: moved _S_IFMT & _S_ISREG to compat.h + +1995-03-28 00:48 millert + + * sudo.c: moved a set of parens + +1995-03-28 00:48 millert + + * strdup.c: now include compat.h + +1995-03-28 00:47 millert + + * parse.yacc: now cast malloc & realloc return vals added search + for HAVE_LSEARCH now use strcmp if no strcasecmp available + +1995-03-28 00:46 millert + + * lsearch.c, emul/search.h: void * -> VOID * + +1995-03-28 00:45 millert + + * config.h.in: removed HAVE_FLEX added VOID added HAVE_DIRENT_H, + HAVE_SYS_NDIR_H, HAVE_SYS_DIR_H, HAVE_NDIR_H added HAVE_LSEARCH + +1995-03-28 00:44 millert + + * compat.h: added _S_IFMT, _S_IFREG, and S_ISREG + +1995-03-28 00:44 millert + + * aclocal.m4: took out SUDO_PROG_INSTALL 1.x to 2.x changes added + echo and results to most SUDO_* macros + +1995-03-28 00:43 millert + + * Makefile.in: no more -I. + +1995-03-28 00:22 millert + + * configure.in: various 1.x ro 2.x autoconf changes now check for + strcasecmp now use AC_INSTALL_PROG instead of custom one added + check for fully woorking void implementation + +1995-03-28 00:02 millert + + * Makefile.in: added lsearch & search.h visudo links into + $(LIBOBJS) + +1995-03-27 23:43 millert + + * aclocal.m4: partial 1.x to 2.x changes added SUDO_FULL_VOID + +1995-03-27 23:40 millert + + * visudo.c: whatnow_help was prototyped to be static be was not + declared as such + +1995-03-27 21:15 millert + + * configure.in: autoconf 2.x changes took out HAVE_FLEX (no longer + used) added check for dirent/dir/ndir.h + +1995-03-27 21:09 millert + + * parse.c: now use groovy gnu autoconf macro AC_HEADER_DIRENT + +1995-03-27 20:38 millert + + * getcwd.c, getwd.c: MAXPATHLEN -> MAXPATHLEN+1 + +1995-03-27 20:23 millert + + * emul/search.h, lsearch.c: Initial revision + +1995-03-27 18:26 millert + + * parse.yacc: eliminated bison warnings + +1995-03-27 17:10 millert + + * parse.lex: added missing case + +1995-03-27 17:04 millert + + * visudo.c: now iincludes signal.h + +1995-03-27 15:16 millert + + * parse.yacc: only clear data structures on a parse error + +1995-03-27 15:01 millert + + * visudo.c: whatnow() now gives help on invalid input + +1995-03-27 14:54 millert + + * visudo.c: added a whatnow() function (sort of like mh) + +1995-03-27 14:53 millert + + * parse.yacc: kill_aliases -> reset_aliases yywrap() now cleans up + by calling reset_aliases() and clearing top took reset stuff out + of yyerror() since it doesn't beling there (and doesn't work + anyway). errorlineno is now initially set to -1 so we can set it + to the first error that occurrs (it was getting set to the last) + +1995-03-27 14:53 millert + + * parse.lex: added a void cast + +1995-03-27 13:26 millert + + * visudo.c: rewrote from scratch based on 4.3BSD vipw.c + +1995-03-26 01:33 millert + + * sudo.c, sudo.h: removed ocmnd + +1995-03-26 01:19 millert + + * sudo.h: no more sudo_realpath() and find_path() changed params + +1995-03-26 01:19 millert + + * sudo.c: find_path() changed since no more realpath() + +1995-03-26 01:18 millert + + * parse.yacc: on error, errorlineno is set to the line where the + error occurred added kill_aliases() to free the aliases struct + now clean up in yyerror() so we can reparse cleanly + +1995-03-26 01:17 millert + + * logging.c: changed to use new find_path() + +1995-03-26 01:17 millert + + * options.h, parse.c: no more USE_REALPATH + +1995-03-26 01:16 millert + + * find_path.c: removed all the realpath() stuff + +1995-03-26 01:16 millert + + * Makefile.in: sudo_realpath.c -> sudo_goodpath.c + +1995-03-26 01:12 millert + + * visudo.c: now works correctly with utk parser + +1995-03-26 00:04 millert + + * goodpath.c: Initial revision + +1995-03-25 23:23 millert + + * sudo_realpath.c: eliminated a compiler warning + +1995-03-25 21:56 millert + + * sudo.c: elinated compiler warning + +1995-03-25 20:40 millert + + * sudo_realpath.c: added sudo_goodpath() + +1995-03-25 20:40 millert + + * sudo.h: added prototype for sudo_goodpath + +1995-03-25 20:39 millert + + * parse.c: added support for /sys/dir.h + +1995-03-25 20:39 millert + + * options.h: USE_REALPATH turned off + +1995-03-25 20:39 millert + + * find_path.c: added calls to sudo_goodpath() + +1995-03-25 20:39 millert + + * configure.in: added check for dirent.h + +1995-03-25 20:38 millert + + * config.h.in: added HAVE_DIRENT_H + +1995-03-25 19:27 millert + + * configure.in: added in linux shadow pass stuff  + +1995-03-24 14:43 millert + + * visudo.c: added back host, user, cmnd, parse_error + +1995-03-24 14:19 millert + + * visudo.c: added in utk changes plus some minor cosmetic changes + +1995-03-24 14:17 millert + + * sudo.c, sudo_realpath.c: added void casts for printf's + +1995-03-24 14:17 millert + + * options.h: added a define of USE_REALPATH + +1995-03-24 14:17 millert + + * configure.in: there is no more visudoers/Makefile + +1995-03-24 14:16 millert + + * Makefile.in: added in utk changes (visudo is now built from the + toplevel) + +1995-03-24 14:15 millert + + * find_path.c: added (void) casts to printf's + +1995-03-23 22:32 millert + + * parse.c, parse.lex, parse.yacc, sudo.h, sudo_realpath.c: merged + in utk changes + +1995-03-22 23:13 millert + + * find_path.c: now check to see that what we are trying to run is a + file (or a link to a file, we do a stat(2) so there is no diff) + +1995-03-13 15:56 millert + + * CHANGES: updated + +1995-03-13 15:56 millert + + * Makefile.in: aclocal.m4 -> acsite.m4 make realclean updated for + new autoconf  + +1995-03-13 15:11 millert + + * sudo.man: added myself as maintainer + +1995-02-16 23:31 millert + + * sudo.c: changed setegid -> setgid + +1995-02-06 17:43 millert + + * configure.in: fixed the test for irix 5.x to skip bad libs + +1995-02-06 17:43 millert + + * aclocal.m4: now initialize OS and OSREV + +1995-01-26 20:52 millert + + * configure.in: irix5 changes + +1995-01-26 20:28 millert + + * configure.in: AC_WITH -> AC_ARG_WITH changes other misc changes + for autoconf 2.1 compatibility + +1995-01-18 19:49 millert + + * visudo.c: use YY_NEW_FILE, not yyrestart since OSF flex doesn't + do the righ thing wrt yyrestart (grrrr) + +1995-01-16 18:44 millert + + * Makefile.in: added visudoers/compat.h to DISTFILES + +1995-01-16 17:01 millert + + * configure.in: fixed an echo + +1995-01-16 16:36 millert + + * sudo.c: added ocmnd declaration adjusted for find_path()'s new + parameters + +1995-01-16 16:35 millert + + * sudo.h: added ocmnd extern adjusted find_path() prototype + +1995-01-16 16:34 millert + + * parse.c: cmndcmp() now takes 3 arguments and checks against the + qualified as well as the unqualified pathname. more code that + should use cmndcmp() but did not, now does + +1995-01-16 16:34 millert + + * options.h: added to a comment + +1995-01-16 16:33 millert + + * logging.c: changed to use new find_path() parameter passing + +1995-01-16 16:32 millert + + * find_path.c: find_path() now takes 2 copyout parameters (one for + the qualified pathname and one for the unqualified pathname). + The third parameter may be NULL. + +1995-01-16 16:31 millert + + * configure.in: no longer munge pathnames.h + +1995-01-16 16:30 millert + + * pathnames.h.in: changed _PATH_* to use _SUDO_PATH_* (which are + defined in config.h) as a result, pathnames.h does not need to be + run through configure and the user can override the configured + values easily. + +1995-01-16 16:30 millert + + * config.h.in: added _SUDO_PATH_* entries + +1995-01-16 16:30 millert + + * aclocal.m4: _PATH* -> _SUDO_PATH_* + +1995-01-16 16:28 millert + + * Makefile.in: updated DISTFILES and HDRS .o's now depend on + config.h + +1995-01-13 12:52 millert + + * compat.h: removed extraneous #endif + +1995-01-13 12:48 millert + + * aclocal.m4: added SUDO_PROG_MV + +1995-01-13 12:47 millert + + * configure.in: added SUDO_PROG_MV added riscos and isc os types + took out -DSHORT_MESSAGE from --with-csops since it is now the + default + +1995-01-13 12:46 millert + + * sudo.c: move the include of id.h to compat.h now includes + options.h + +1995-01-13 12:45 millert + + * sudo.h: moved compatibility #defines to compat.h + +1995-01-13 12:45 millert + + * pathnames.h.in: added _PATH_MV + +1995-01-13 12:43 millert + + * config.h.in: move __P to compat.h + +1995-01-13 12:39 millert + + * getcwd.c, getwd.c, putenv.c: now includes compat.h + +1995-01-13 12:39 millert + + * compat.h: Initial revision + +1995-01-11 19:11 millert + + * sudo.h: pull user-configurable stuff out and put in options.h + +1995-01-11 18:43 millert + + * check.c, find_path.c, logging.c, parse.c, sudo_realpath.c, + sudo_setenv.c, parse.lex, parse.yacc, visudo.c: now includes + options.h + +1995-01-11 18:41 millert + + * Makefile.in: added visudoers/options.h + +1995-01-11 18:40 millert + + * options.h, OPTIONS: Initial revision + +1995-01-11 18:39 millert + + * Makefile.in: added OPTIONS and options.h + +1995-01-11 18:36 millert + + * logging.c: changed #ifdef's to use LOGGING and + SLOG_SYSLOG/SLOG_FILE + +1995-01-11 11:02 millert + + * check.c, sudo.h: changed PASSWORD_TIMEOUT to minutes + +1994-12-17 18:18 millert + + * visudo.c: now only do Editor +line_num if line_num != 0 + +1994-12-15 21:06 millert + + * visudo.c: now use mv if rename(2) fails + +1994-12-15 20:32 millert + + * BUGS: added a visudo bug + +1994-12-15 19:46 millert + + * check.c: expanded comment + +1994-11-12 18:33 millert + + * check.c: fixed user_is_exempt to return 0 if EXEMPTGROUP is not + set + +1994-11-09 19:49 millert + + * sudo.c: added mips & isc support + +1994-11-09 19:49 millert + + * parse.c: added support for non-root owned sudoers file + +1994-11-09 19:48 millert + + * check.c: added exempt group support + +1994-11-09 19:47 millert + + * sudo.h: added set_perms() support added SUDOERS_OWNER so can have + non-root own sudoers file added exempt group support added isc + support + +1994-11-09 19:46 millert + + * visudo.c: now copy sudoers to temp file via read/write (not + stdio) now chown new sudoers file to SUDOERS_OWNER + +1994-11-07 20:40 millert + + * configure.in: added skey support + +1994-11-07 20:39 millert + + * sudo.h: fixed typo added set_perms support added skey support + added seteuid()/setegid() emulation for AIX + +1994-11-07 20:38 millert + + * sudo.c: be_* -> setperms() now check to make sure sudoers file is + owned by root nread/write by only root + +1994-11-07 20:38 millert + + * logging.c, parse.c, sudo_realpath.c: be_* -> setperms() + +1994-11-07 20:38 millert + + * check.c: be_* -> set_perms() added skey support + +1994-11-06 18:59 millert + + * Makefile.in: ++version + +1994-11-06 18:59 millert + + * version.h: ++ + +1994-10-21 13:16 millert + + * sudo.c: now sets IFS + +1994-10-21 12:02 millert + + * insults.h: fixed typo + +1994-10-15 15:48 millert + + * config.h.in: added HAVE_SKEY + +1994-10-04 13:00 millert + + * CHANGES: updated + +1994-10-04 12:57 millert + + * Makefile.in: ++version + +1994-10-04 12:57 millert + + * version.h: ++ + +1994-10-04 12:56 millert + + * sudo.c: now bail if ARgv[1] > MAXPATHLEN + +1994-10-04 12:56 millert + + * configure.in: added function check for tcgetattr(3) + +1994-10-04 12:55 millert + + * config.h.in: only define HAVE_TERMIOS_H if you have tcgetattr(3) + +1994-10-04 12:53 millert + + * config.h.in: added check for tcgetattr + +1994-09-26 17:38 millert + + * CHANGES: updated + +1994-09-22 13:30 millert + + * parse.lex: now only include unistd.h for linux + +1994-09-21 14:29 millert + + * Makefile.in: added visudo.8 generation + +1994-09-21 14:07 millert + + * configure.in: added -Wl,-bI:./aixcrypt.exp to aix flags + +1994-09-20 19:39 millert + + * BUGS: added one + +1994-09-20 19:39 millert + + * CHANGES: updated + +1994-09-20 19:38 millert + + * README: added mailing list info + +1994-09-20 19:37 millert + + * parse.yacc: now use sudolineno instead of yylineno fixed bison + warnings + +1994-09-20 19:37 millert + + * configure.in: now use -no_library_replacement for osf don't make + a static binary for hpux >= 9.0 + +1994-09-20 19:21 millert + + * tgetpass.c: added string.h/strings.h inclusion + +1994-09-20 19:21 millert + + * config.h.in: added ssize_t def + +1994-09-20 19:18 millert + + * parse.lex: added inclusion of string.h/strings.h + +1994-09-20 18:48 millert + + * aclocal.m4: fixed uname | sed (needed to quote the '[') + +1994-09-20 18:42 millert + + * parse.lex: replaced yylineno with sudolineno fixed bison syntax + errors + +1994-09-20 18:13 millert + + * visudo.c: changed yylineno to sudolineno since yylineno cannot be + counted upon. + +1994-09-20 18:10 millert + + * TODO: updated + +1994-09-20 17:52 millert + + * parse.c: added code to support command listings + +1994-09-20 17:36 millert + + * sudo.c: added code for -l flag + +1994-09-20 17:35 millert + + * sudo.man: fixed typo added info for -l flag + +1994-09-20 14:45 millert + + * configure.in: AC_SSIZE_T -> SUDO_SSIZE_T + +1994-09-20 14:45 millert + + * aclocal.m4: added SUDO_SSIZE_T + +1994-09-20 14:44 millert + + * sudo.h: added MODE_LIST + +1994-09-20 14:43 millert + + * configure.in: added AC_SSIZE_T + +1994-09-19 20:53 millert + + * find_path.c, sudo_realpath.c: readlink() is now declared as + returning ssize~_t + +1994-09-19 20:44 millert + + * configure.in: added -laud for OSF c2 + +1994-09-02 15:55 millert + + * config.h.in, parse.lex, parse.yacc, pathnames.h.in, visudo.c, + Makefile.in: changed sudo-bugs.cs.colorado.edu -> + sudo-bugs@cs.colorado.edu + +1994-09-02 15:54 millert + + * check.c, find_path.c, getcwd.c, getwd.c, insults.h, logging.c, + parse.c, putenv.c, strdup.c, sudo.c, sudo.h, sudo_realpath.c, + sudo_setenv.c, tgetpass.c, version.h: changed + sudo-bugs.cs.colorado.edu -> sudo-bugs@cs.colorado.ed + +1994-09-01 15:56 millert + + * Makefile.in: ++version + +1994-09-01 15:55 millert + + * version.h: ++ + +1994-09-01 15:55 millert + + * logging.c: added host to alertmail messages + +1994-09-01 15:55 millert + + * CHANGES, TODO: udpated + +1994-09-01 15:26 millert + + * logging.c: fixed logging problem where mail would not say which + user it was + +1994-09-01 13:45 millert + + * configure.in: added -laud for gcc if osf & c2 + +1994-09-01 13:39 millert + + * check.c: moved set_auth_parameters to sudo.c + +1994-09-01 13:38 millert + + * sudo.c: added set_auth_parameters for osf + +1994-09-01 13:22 millert + + * configure.in: cleaned up -static stuff + +1994-09-01 13:15 millert + + * Makefile.in: ++version + +1994-09-01 13:15 millert + + * version.h: ++ + +1994-09-01 13:15 millert + + * sudo.c: changed setenv() to sudo_setenv() + +1994-09-01 13:12 millert + + * check.c: fixed osf problem + +1994-08-31 22:17 millert + + * configure.in: added OSF C2 stuff + +1994-08-31 22:00 millert + + * CHANGES: updated + +1994-08-31 21:56 millert + + * check.c: added osf auth support & removed some extra spaces + +1994-08-31 21:52 millert + + * INSTALL, SUPPORTED: added osf C2 stuff + +1994-08-31 19:52 millert + + * TODO: added 2 suggestions + +1994-08-31 19:33 millert + + * Makefile.in: removed README.v1.3.1 and added VERSION stuff + +1994-08-31 18:48 millert + + * version.h: pl1 + +1994-08-30 18:31 millert + + * version.h: 1.3.1final + +1994-08-30 18:30 millert + + * Makefile.in: added HISTORY + +1994-08-30 18:30 millert + + * sudo.man: mention HISTPRY file + +1994-08-30 18:30 millert + + * sudo.c: use sizeof instead of a constant in 1 place + +1994-08-30 18:30 millert + + * parse.yacc: added unistd.h + +1994-08-30 18:29 millert + + * parse.lex: added unistd.h + +1994-08-30 18:27 millert + + * README: udpated + +1994-08-30 18:15 millert + + * HISTORY: Initial revision + +1994-08-17 12:45 millert + + * version.h: ++ + +1994-08-17 12:39 millert + + * CHANGES: updated + +1994-08-17 12:36 millert + + * sudo_setenv.c: added unistd.h include + +1994-08-16 15:46 millert + + * sudo.c: added sys/time.h for AIX + +1994-08-14 21:22 millert + + * configure.in: added check for -lsocket and sys/sockio.h + +1994-08-14 21:21 millert + + * config.h.in: took out libshadow check and added in sys/sockio.h + check + +1994-08-14 21:21 millert + + * sudo.c: now include sockio.h instead of ioctl.h if it exists + "sudo -" now gets a better error message + +1994-08-14 20:47 millert + + * sample.sudoers: now has a dir and subnet entry + +1994-08-13 18:15 millert + + * sudo.c: removed if_ether.h + +1994-08-13 17:16 millert + + * TODO: added an item + +1994-08-13 17:15 millert + + * sudo.man: added network and ip addresses to man page + +1994-08-13 17:09 millert + + * sudo.c: no error if can't get interfaces or netmask since + networking may not be in the kernel. + +1994-08-13 17:08 millert + + * parse.c: nwo check for interfaces == NULL + +1994-08-12 21:22 millert + + * parse.c: fixed a bug that caused directory specs in a Cmnd_Alias + to fail if the last entry in the spec failed (ie: it was only + looking at the last entry). CLeaned things up by adding the + cmndcmp() function--all neat & tidy + +1994-08-12 21:21 millert + + * CHANGES: added one + +1994-08-11 23:42 millert + + * sudo.c: now do two passes to skip bogus interfaces (lo0, etc) + +1994-08-11 21:58 millert + + * logging.c, sudo_realpath.c, sudo_setenv.c: added ninclude of + netinet/in.h + +1994-08-11 21:58 millert + + * check.c, find_path.c, getcwd.c, getwd.c, parse.lex, parse.yacc, + visudo.c: added include of netinet/in.h + +1994-08-11 21:57 millert + + * version.h: ++ + +1994-08-11 21:57 millert + + * sudo.h: added interfaces global + +1994-08-11 21:56 millert + + * parse.c: now uses new interfaces global + +1994-08-11 21:56 millert + + * sudo.c: now ip addresses are gleaned fw/o dns + +1994-08-10 19:21 millert + + * sudo.c: added load_ip_addrs() to load the ip_addrs global var + +1994-08-10 19:21 millert + + * parse.c: added hostcmp() to compare hostnames, ip addrs, and + network addrs + +1994-08-10 19:20 millert + + * sudo.h: added ip_addrs def added load_ip_addrs prototype + +1994-08-08 16:03 millert + + * CHANGES: updated + +1994-08-08 15:57 millert + + * Makefile.in: removed multiple entries in DISTFILES + +1994-08-08 13:05 millert + + * visudo.c: ansified the !STDC_HEADERS decls + +1994-08-08 13:05 millert + + * find_path.c, getcwd.c, getwd.c, putenv.c, strdup.c: don't do + malloc decl if gnuc + +1994-08-08 13:04 millert + + * sudo.c: can't use getopt(3) since it munges args to the command + to be run as root don't do malloc decl if gnuc + +1994-08-08 00:41 millert + + * find_path.c, getcwd.c, getwd.c, putenv.c, strdup.c, sudo.c, + sudo_realpath.c, sudo_setenv.c: ansi-fied !STDC_HEADER function + prottypes + +1994-08-08 00:27 millert + + * getcwd.c, getwd.c: added missing paren + +1994-08-08 00:23 millert + + * Makefile.in: added putenv.c to DISTFILES + +1994-08-08 00:08 millert + + * sudo_setenv.c: added params to func decls when STDC_HEADERS is + not defined now can count on putenv() being there + +1994-08-08 00:08 millert + + * sudo_realpath.c: took out errno decl since sudo.h does it for us + fixed up a next cc warning added params to func decls when + STDC_HEADERS is not defined + +1994-08-08 00:07 millert + + * sudo.h: took out environ extern added local declaratio of + putenv() if local version is needed + +1994-08-08 00:05 millert + + * find_path.c, getcwd.c, getwd.c, strdup.c, sudo.c: added params to + func decls when STDC_HEADERS is not defined + +1994-08-08 00:04 millert + + * config.h.in: added memcpy check check to see that ansi vs bsd + macros are ntot already defiend before defining (ie: avoid + redefinition) + +1994-08-08 00:03 millert + + * configure.in: removed fluff setenv check plus check w/ replace + for putenv if also no setenv + +1994-08-08 00:01 millert + + * putenv.c: Initial revision + +1994-08-06 19:19 millert + + * sudo_setenv.c: Initial revision + +1994-08-06 19:19 millert + + * sudo.h: rm'd s realp[ath added sudo_realpath and sudo_setenv + +1994-08-06 19:19 millert + + * sudo.c: now use sudo_setenvc + +1994-08-06 19:18 millert + + * configure.in: added puteenv and setenv, removed realpath + +1994-08-06 19:18 millert + + * config.h.in: added putenv & setenv + +1994-08-06 19:18 millert + + * Makefile.in: added sudo_setenv + +1994-08-06 19:16 millert + + * version.h: ++ + +1994-08-05 19:43 millert + + * configure.in: added MAN_POSTINSTALL and /usr/share/catman for + irix + +1994-08-05 19:43 millert + + * Makefile.in: added MAN_POSTINSTALL + +1994-08-05 19:43 millert + + * CHANGES: added + +1994-08-05 19:10 millert + + * sudo.man: added SUDO_* plus new options + +1994-08-05 19:10 millert + + * CHANGES: added one + +1994-08-05 19:07 millert + + * configure.in: took out shadow lib + +1994-08-05 18:35 millert + + * TODO: adde done + +1994-08-05 17:52 millert + + * visudo.c: now use yyrestart() if flex now reset yylineno to 0 + +1994-08-05 17:49 millert + + * Makefile.in: support for installing a cat page instead of a man + page if no nroff + +1994-08-05 17:48 millert + + * configure.in: now defines HAVE_FLEX fixed up man stuff so that it + looks for nroff to determine whether or not to install a cat or + man page + +1994-08-05 17:48 millert + + * config.h.in: added HAVE_FLEX + +1994-08-05 16:14 millert + + * sudo.c: not set ret to MODE_RUN initially + +1994-08-05 16:12 millert + + * find_path.c: made command (and therefor cmnd dynamically + allocated) + +1994-08-04 20:25 millert + + * TODO: did #8 + +1994-08-04 20:24 millert + + * version.h: ++ + +1994-08-04 20:24 millert + + * sudo_realpath.c: changed bufs from MAXPATHLEN to MAXPATHLEN+1 + +1994-08-04 20:24 millert + + * sudo.h: added MODE_ removed validate_only and added + remove_timestamp() + +1994-08-04 20:22 millert + + * sudo.c: usage() now takes an int (exit value) added parse_args() + to parse command line arguments moved call to find_path() from + load_globals to new function load_cmnd() removed validate_only + global -- now use the concept of "modes" added -h and -k options + +1994-08-04 20:21 millert + + * parse.c: no longer use global validate_only now checks for + command called "validate" removed check for non-fully qualified + commands since that is done by find_path + +1994-08-04 20:20 millert + + * find_path.c: changed MAXPATHLEN r to MAXPATHLEN+1 + +1994-08-04 20:17 millert + + * find_path.c: fixed off by one error with MAXPATHLEN and fixed a + comment + +1994-08-04 20:17 millert + + * check.c: check_timestamp no longer runs reminder(), it is implied + in the return val added remove_timestamp() + +1994-08-04 20:16 millert + + * CHANGES: updated + +1994-08-04 16:38 millert + + * BUGS: fixed on + +1994-08-04 16:38 millert + + * sudo_realpath.c: took out old_errno + +1994-08-04 16:37 millert + + * CHANGES: updated + +1994-08-03 12:08 millert + + * logging.c: moved send_mail to after syslog + +1994-08-02 22:41 millert + + * sudo.c: now set SUDO_ envariables + +1994-08-01 13:40 millert + + * version.h: ++ + +1994-08-01 13:39 millert + + * sudo_realpath.c: now print error if chdir fails + +1994-08-01 13:39 millert + + * find_path.c: removed an XXX + +1994-07-25 20:40 millert + + * CHANGES: updated + +1994-07-25 20:36 millert + + * configure.in: no more static binaries for aix + +1994-07-25 18:37 millert + + * INSTALL: fixed typo + +1994-07-25 18:33 millert + + * sudo_realpath.c: took out stuff not needed for sudo now does + be_root/be_user itself now uses cwd global + +1994-07-25 18:32 millert + + * version.h: +=2 + +1994-07-25 18:31 millert + + * logging.c, sudo.c: be_root/be_user is now down in sudo_realpath() + +1994-07-25 18:26 millert + + * logging.c, sudo.h: now works with 4.2BSD syslog (blech) + +1994-07-25 18:25 millert + + * find_path.c: now use sudo_realpath() + +1994-07-25 18:25 millert + + * config.h.in: took out realpth() stuff since we now use + sudo_realpath() + +1994-07-25 18:25 millert + + * configure.in: ultrix enhanced sec + +1994-07-25 18:25 millert + + * SUPPORTED: added ultrix enhanced sec. + +1994-07-25 18:24 millert + + * INSTALL: updated + +1994-07-25 18:21 millert + + * check.c: ultrix enhanced security suport + +1994-07-25 18:20 millert + + * Makefile.in: added sudo_realpath.c + +1994-07-25 18:18 millert + + * CHANGES: updated + +1994-07-25 14:28 millert + + * tgetpass.c: increased passwd len to 24 for c2 security + +1994-07-25 13:17 millert + + * BUGS: updated BUGS + +1994-07-15 11:49 millert + + * check.c: now use user global var + +1994-07-15 11:48 millert + + * configure.in: took out -ls + +1994-07-14 19:11 millert + + * configure.in: added AFS libs + +1994-07-14 17:45 millert + + * sudo.h: user is now a char * added epasswd + +1994-07-14 17:43 millert + + * sudo.c: added tzset() to load_globals added epasswd (encrypted + password) global made user dynamically allocated + +1994-07-14 17:43 millert + + * configure.in: added tzset test + +1994-07-14 17:43 millert + + * config.h.in: added HAVE_TZSET + +1994-07-14 17:42 millert + + * check.c: cleaned up encrypted passwd grab somewhat + +1994-07-14 12:34 millert + + * configure.in: fixed AFS typo + +1994-07-14 12:34 millert + + * INSTALL: added AFS not + +1994-07-14 12:34 millert + + * CHANGES: udpated + +1994-07-14 12:33 millert + + * logging.c: can now log to both syslog & a file + +1994-07-14 12:12 millert + + * sudo.h: added BOTH_LOGS + +1994-07-14 11:34 millert + + * CHANGES: updated + +1994-07-14 11:32 millert + + * configure.in: --with-AFS + +1994-07-14 11:32 millert + + * config.h.in: added HAVE_AFS + +1994-07-14 11:31 millert + + * check.c: added afs changes + +1994-07-14 11:21 millert + + * sudo.h: removed AFS stuff :-) + +1994-07-14 11:19 millert + + * tgetpass.c: include sys/select for AIX + +1994-07-14 11:17 millert + + * sudo.h: added AFS + +1994-07-14 11:16 millert + + * version.h: ++ + +1994-07-07 14:45 millert + + * SUPPORTED, CHANGES: updated + +1994-07-07 14:44 millert + + * logging.c: can now have MAILER undefined + +1994-07-07 14:37 millert + + * INSTALL: new sub-note about MAILER + +1994-07-06 23:11 millert + + * sudo.man: added blurb about password timeout + +1994-07-06 20:52 millert + + * configure.in: convex c2 changes + +1994-07-06 20:52 millert + + * aclocal.m4: took out duplicate define of _CONVEX_SOURCE + +1994-07-06 20:51 millert + + * Makefile.in: added OSDEFS + +1994-07-06 20:46 millert + + * config.h.in: added spaces + +1994-07-06 20:08 millert + + * tgetpass.c: added a goto if fgets fails + +1994-07-06 20:08 millert + + * sudo.h: use __hpux not hpux convex c2 stuff + +1994-07-06 20:08 millert + + * sudo.c: use __hpux not hpux + +1994-07-06 20:08 millert + + * logging.c: convex c2 stuff + +1994-07-06 20:07 millert + + * config.h.in: define ansi-ish cpp os defines if non-ansi are + defined for hpux & convex + +1994-07-06 20:07 millert + + * INSTALL: updated to say we support sonvex C2 + +1994-07-06 20:05 millert + + * check.c: added convex c2 support + +1994-07-01 12:06 millert + + * tgetpass.c: no more ioctl never returns NULL uses fgets() and + select() to timeout + +1994-06-29 17:04 millert + + * configure.in: things were testing -n "$GCC" instead of -z "$GCC" + +1994-06-29 16:39 millert + + * tgetpass.c: now works + uses fgets() + +1994-06-28 18:25 millert + + * tgetpass.c: select doesn't seem to recognize a single '\n' as + input waiting so we can;t use it, sigh. + +1994-06-26 16:38 millert + + * PORTING: updated tgetpass() blurb + +1994-06-26 16:35 millert + + * configure.in: added --with-getpass + +1994-06-26 16:35 millert + + * Makefile.in: added tgetpass stuff + +1994-06-26 15:25 millert + + * tgetpass.c: now uses stdio + +1994-06-26 15:17 millert + + * version.h: ++ + +1994-06-24 19:48 millert + + * PORTING: updated ,. + +1994-06-24 19:46 millert + + * config.h.in: added USE_GETPASS && HAVE_C2_SECURITY + +1994-06-24 19:45 millert + + * configure.in: fixed a test aded --with-C2 and --with-tgetpass + +1994-06-24 19:45 millert + + * check.c: added hpux C2 shit + +1994-06-24 19:45 millert + + * Makefile.in: took out tgetpass.* + +1994-06-24 19:45 millert + + * INSTALL: added C2 blurb + +1994-06-13 15:54 millert + + * configure.in: no termio(s) for ultrix since it is broken + +1994-06-13 15:41 millert + + * check.c: added a space (yeah, anal) + +1994-06-13 15:17 millert + + * realpath.c, sudo_realpath.c: fixed it (duh, rtfm) + +1994-06-08 14:34 millert + + * config.h.in: took out bsd signal stuff for irix + +1994-06-08 14:26 millert + + * visudo.c: comments in #endif + +1994-06-08 14:09 millert + + * configure.in: don't define BSD signals for irix + +1994-06-08 12:57 millert + + * TODO: did some... + +1994-06-08 12:57 millert + + * CHANGES: updated + +1994-06-08 12:56 millert + + * realpath.c, sudo_realpath.c: took out unneeded code by changing + where a strings was terminated + +1994-06-07 19:21 millert + + * realpath.c, sudo_realpath.c: fix bug where /dirname would return + NULL + +1994-06-07 17:40 millert + + * sudo.h: move __P to config.h + +1994-06-07 17:40 millert + + * getcwd.c, getwd.c, realpath.c, sudo_realpath.c: added errno + definition + +1994-06-07 17:40 millert + + * config.h.in: added __P + +1994-06-07 17:21 millert + + * config.h.in: added HAVE_FCHDIR + +1994-06-07 17:18 millert + + * strdup.c: now include stdio + +1994-06-07 14:55 millert + + * realpath.c, sudo_realpath.c: now works if no fchdir + +1994-06-07 14:55 millert + + * visudo.c: define SA_RESETHAND to null if not defined + +1994-06-07 14:54 millert + + * configure.in: added check & replace + +1994-06-06 20:05 millert + + * configure.in: took out -static for nextstep -- it doesn't work + +1994-06-06 19:59 millert + + * logging.c: moved #endif to where it belongs + +1994-06-06 19:54 millert + + * SUPPORTED: correction + +1994-06-06 19:42 millert + + * configure.in: now checks for strdup realpath getcwd bzero + +1994-06-06 19:31 millert + + * config.h.in: emulate bzero + +1994-06-06 16:57 millert + + * visudo.c: added posic signals + +1994-06-06 16:57 millert + + * tgetpass.c: bzero cast + +1994-06-06 16:57 millert + + * logging.c: added posix signals + +1994-06-06 16:56 millert + + * configure.in: removed BROKEN_GETPASS added new srcs toreplace + missing functions + +1994-06-06 16:56 millert + + * config.h.in: added posix signal stuff + +1994-06-06 16:56 millert + + * Makefile.in: added new srcs + +1994-06-06 12:53 millert + + * visudo.c: updated useag + +1994-06-06 12:39 millert + + * tgetpass.c: now uses posix signals + +1994-06-05 20:17 millert + + * PORTING: updated sto reflect major changes + +1994-06-05 20:05 millert + + * TODO, CHANGES: updated + +1994-06-05 20:04 millert + + * tgetpass.c: uses sysconf() if available + +1994-06-05 20:04 millert + + * sudo.h: added PASSWORD_TIMEOUT + prototypes for new functions + +1994-06-05 20:04 millert + + * realpath.c, sudo_realpath.c: for those w/o this in libc + +1994-06-05 20:03 millert + + * getcwd.c, getwd.c: Initial revision + +1994-06-05 20:03 millert + + * find_path.c: rewrote to use realpath(3) - nis now all my code + +1994-06-05 20:02 millert + + * config.h.in: added HAVE_REALPATH + +1994-06-05 20:02 millert + + * check.c: now use tgetpass + +1994-06-05 20:02 millert + + * Makefile.in: added LIBOBJS use tgetpass.c + +1994-06-05 18:55 millert + + * tgetpass.c: works now :-) + +1994-06-05 18:27 millert + + * tgetpass.c: Initial revision + +1994-06-05 17:17 millert + + * pathnames.h.in: added /dev/tty + +1994-06-04 17:12 millert + + * version.h: incremented + +1994-06-04 15:29 millert + + * sudo.c: always use getcwd + +1994-06-04 14:49 millert + + * config.h.in: added check for getwd + +1994-06-04 14:48 millert + + * configure.in: replace strdup & realpath & getcwd if missing + +1994-06-04 14:47 millert + + * pathnames.h.in: added _PATH_PWD + +1994-06-04 14:46 millert + + * aclocal.m4: added SUDO_PROG_PWD + +1994-06-04 14:37 millert + + * realpath.c, sudo_realpath.c, strdup.c: Initial revision + +1994-06-03 11:31 millert + + * configure.in: quoted quare brackets + +1994-06-02 17:49 millert + + * sudo.c: no need to strdup() a constant + +1994-06-02 15:45 millert + + * CHANGES: updated + +1994-06-02 15:44 millert + + * sudo.man: added validate + +1994-06-02 15:42 millert + + * sudo.c: added -v to usage + +1994-06-02 15:41 millert + + * parse.c, sudo.c, sudo.h: added validate_only stuff + +1994-05-29 21:29 millert + + * configure.in: now finds sed + +1994-05-29 21:28 millert + + * aclocal.m4: $OSREV is now an int + +1994-05-29 19:13 millert + + * configure.in: added mtxinu to caser + +1994-05-29 18:37 millert + + * sudo.h: added EXEC macro + +1994-05-29 18:36 millert + + * sudo.c: now use the EXEC nmacro now only do a gethostbyname() if + FQDN is set + +1994-05-29 18:36 millert + + * logging.c: changed mail_argv[] def now use EXEC() macro + +1994-05-29 18:35 millert + + * check.c: took out crypt() definition + +1994-05-29 17:23 millert + + * version.h: upped the version + +1994-05-29 15:52 millert + + * configure.in: always look for -lnsl + +1994-05-29 15:29 millert + + * aclocal.m4: added an echo + +1994-05-29 15:25 millert + + * sudo.h: SHORT_MESSAGE is now the default + +1994-05-29 15:18 millert + + * config.h.in: fixed typo + +1994-05-29 01:29 millert + + * configure.in: added missing AC_DEFINE(SVR4) for solaris + +1994-05-28 20:42 millert + + * sudo.man: documented the -v flag + +1994-05-28 20:34 millert + + * SUPPORTED: updated + +1994-05-28 20:31 millert + + * check.c: proto-ized crypt() + +1994-05-28 20:28 millert + + * config.h.in: added LIBSHADOW undef + +1994-05-28 20:18 millert + + * configure.in: nwo set OS to be lowercase + +1994-05-28 19:36 millert + + * configure.in: now use SUDO_OSTYPE to set $OS + +1994-05-28 19:36 millert + + * aclocal.m4: now use uname to determine os + +1994-05-28 16:23 millert + + * visudo.c: added prototypes & moved sig handler around + +1994-05-28 15:13 millert + + * sudo.h: added prototyppes + +1994-05-28 15:13 millert + + * parse.c: added comment + +1994-05-28 15:12 millert + + * config.h.in: nwo use _BSD_SIGNALS not _BSD_COMPAT + +1994-05-28 15:11 millert + + * check.c, logging.c, sudo.c: added prototypes + +1994-05-28 15:11 millert + + * aixcrypt.exp: Initial revision + +1994-05-28 15:11 millert + + * Makefile.in: added aixcrypt.exp + +1994-05-28 13:21 millert + + * parse.lex, parse.yacc: moved config.h to top of includes + +1994-05-25 15:48 millert + + * find_path.c: now don't bitch if get EACCESS (treat like EPERM) + +1994-05-24 23:08 millert + + * visudo.c: added -v flag and usage() + +1994-05-24 23:08 millert + + * version.h: fixed a typo + +1994-05-24 23:08 millert + + * sudo.c: cast Argv to a const for exec added -v flag + +1994-05-24 23:07 millert + + * logging.c: mail_argv is now a const + +1994-05-24 23:07 millert + + * configure.in: only set RETSIGTYPE if it is not set already + +1994-05-24 23:07 millert + + * aclocal.m4: now defines & STDC_HEADERS for Irix + +1994-05-24 23:07 millert + + * Makefile.in: added version.h + +1994-05-24 21:25 millert + + * insults.h, sudo.h: prevent multiple inclusion + +1994-05-24 21:20 millert + + * version.h: Initial revision + +1994-05-24 21:09 millert + + * parse.lex, parse.yacc: now includes config.h + +1994-05-24 20:54 millert + + * aclocal.m4: now talks about sunos 4.x + +1994-05-24 20:23 millert + + * visudo.c: calls to Exit now pass an arg + +1994-05-24 18:00 millert + + * visudo.c: signal handler now takes an int argument + +1994-05-24 18:00 millert + + * CHANGES: updated + +1994-05-24 17:44 millert + + * sudo.c: ok, the getcwd() is now *really* done as the user + +1994-05-24 17:44 millert + + * configure.in: changed AIX STATIC_FLAGS + +1994-05-24 16:27 millert + + * aclocal.m4: solaris now defines SVR4 + +1994-05-24 16:18 millert + + * sudo.h: added cwd and fixed stupid core dump that makes no sense. + sigh. + +1994-05-24 16:18 millert + + * sudo.c: moved getcwd stuff into load_globals + +1994-05-24 16:18 millert + + * parse.c: took out externs that are in suod.h + +1994-05-24 16:18 millert + + * logging.c: moved cwd into load_globals + +1994-05-24 16:17 millert + + * find_path.c: moved cwd stuff + +1994-05-24 15:55 millert + + * Makefile.in: fixed make distclean & realclean + +1994-05-24 12:51 millert + + * TODO: updated ., + +1994-05-24 12:51 millert + + * CHANGES: added solaris changes + +1994-05-24 12:51 millert + + * aclocal.m4: added solaris changes, need to rework + +1994-05-24 12:50 millert + + * configure.in: cleaned up for solaris + +1994-05-24 12:13 millert + + * logging.c: reinstall reapchild signal handler for non-bsd signals + +1994-05-24 12:03 millert + + * sudo.h: took out getdtablesize() emulation for HP-UX (no longer + needed) + +1994-05-24 12:03 millert + + * sudo.c: support for HAVE_SYSCONF + +1994-05-24 12:02 millert + + * visudo.c: added for solaris & reorg'd the includes + + minor prettying up / + +1994-05-23 20:26 millert + + * config.h.in: added HAVE_SYSCONF + +1994-05-16 18:57 millert + + * configure.in: now tells you what os you are running /. + +1994-05-16 18:56 millert + + * aclocal.m4: took out extra ',' + +1994-05-14 17:56 millert + + * config.h.in: added _BSD_COMPAT + +1994-05-14 17:56 millert + + * aclocal.m4: fixed for irix5 + +1994-05-14 17:55 millert + + * CHANGES: updated + +1994-05-14 17:27 millert + + * sudo.c: uid seinitialized to -2 + +1994-04-28 12:36 millert + + * sudo.c: now removes LIBPATH for AIX + +1994-03-12 20:41 millert + + * configure.in: now uses ufc if it finds it + +1994-03-12 17:42 millert + + * sudo.h: no longer define yyval & yylval since yacc does it + +1994-03-12 17:42 millert + + * parse.lex: now defines yylval as extenr + +1994-03-12 17:41 millert + + * configure.in: BROKEN_GETPASS is now an OPTION + +1994-03-12 17:41 millert + + * config.h.in: took out BROKEN_GETPASS + +1994-03-12 17:20 millert + + * Makefile.in: took out big comment + +1994-03-12 16:24 millert + + * README: updated + +1994-03-12 16:20 millert + + * Makefile.in: took out README.beta + +1994-03-12 16:19 millert + + * SUPPORTED: Initial revision + +1994-03-12 16:19 millert + + * INSTALL: now reference SUPPORTED ., + +1994-03-12 16:17 millert + + * config.h.in: now check for convex OR __convex__ + +1994-03-12 16:16 millert + + * aclocal.m4: now check for convex or __convex__ + +1994-03-12 16:15 millert + + * Makefile.in: added dist target + +1994-03-12 15:19 millert + + * aclocal.m4: use __convex__ + +1994-03-12 14:33 millert + + * find_path.c: now use _S_* stat stuff to be ansi-like + +1994-03-12 14:11 millert + + * INSTALL: updated for configure directions + +1994-03-12 14:05 millert + + * Makefile.in: distclean now removes config.h and pathnames.h + +1994-03-12 14:03 millert + + * CHANGES: updated + +1994-03-12 14:00 millert + + * TODO: fixed typoe + +1994-03-12 13:57 millert + + * Makefile.in, visudo.c: updated version + +1994-03-12 13:57 millert + + * config.h.in, pathnames.h.in: added copyright header + +1994-03-12 13:55 millert + + * check.c, find_path.c, insults.h, logging.c, parse.c, parse.lex, + parse.yacc, sudo.c, sudo.h: udpated version + +1994-03-12 13:39 millert + + * visudo.c: udpated to use configure + pathnames.h + +1994-03-12 13:37 millert + + * Makefile.in, config.h.in, configure.in, aclocal.m4: updated + +1994-03-12 13:37 millert + + * sudo.h: now works with configure + +1994-03-12 13:36 millert + + * check.c, find_path.c, getpass.c, logging.c, parse.c, sudo.c: + updated to work with configure + pathnames.h + +1994-03-12 10:40 millert + + * Makefile.in: added LEXLIB + +1994-03-10 03:18 millert + + * COPYING: updated gnu general licence to versio 2 + +1994-03-10 02:44 millert + + * pathnames.h.in, config.h.in: Initial revision + +1994-03-10 01:43 millert + + * sudo.h: changed to work with configure + +1994-03-09 18:51 millert + + * Makefile.in, aclocal.m4, configure.in: Initial revision + +1994-03-09 17:36 millert + + * visudo.c: now uses defines used by configure + +1994-03-01 16:31 millert + + * find_path.c: sudo won't bitch about EPERM now, for real + +1994-02-28 00:36 millert + + * logging.c: renamed exec_argv to eliminate a libc name clash with + ksros + +1994-02-28 00:28 millert + + * CHANGES: corrected + +1994-02-28 00:27 millert + + * logging.c, sudo.c, sudo.h: execve -> execv + +1994-02-27 23:27 millert + + * TODO: upated + +1994-02-27 23:19 millert + + * PORTING: added 2 mroe items + +1994-02-27 23:12 millert + + * CHANGES: updated + +1994-02-27 23:11 millert + + * sudo.h: added UMASK and mode_t declaration + +1994-02-27 23:11 millert + + * sudo.c: added UMASK + +1994-02-27 20:55 millert + + * logging.c: now opens log file with mode 077 + +1994-02-27 20:55 millert + + * check.c: saved current umask ans restores it + +1994-02-27 20:36 millert + + * sudo.h: added MAXLOGFILELEN + +1994-02-27 20:35 millert + + * logging.c: split long log lines. FOr syslog, split into multiple + entries, for a log file, indent the extra for readability + +1994-02-27 17:22 millert + + * CHANGES: added changes + +1994-02-27 17:18 millert + + * sudo.h: MAXLOGLEN & MAXSYSLOGLEN are now different (as they + should be) + +1994-02-25 16:04 millert + + * TODO: added input from Brett M Hogden + +1994-02-16 13:35 millert + + * sudo.c: added rmenv() to remove stuff from environ. can now uses + execvp() OR execve() becuase of this. + +1994-02-16 13:35 millert + + * logging.c: now uses execvp() OR execve() + +1994-02-16 13:31 millert + + * sudo.h: added USE_EXECVE + +1994-02-16 13:27 millert + + * sudo.h: added environ + +1994-02-16 12:53 millert + + * find_path.c: now ignore EPERM + +1994-02-15 23:52 millert + + * sudo.h: moved some func decls out of sudo.h and into sudo.c as + statics /. + +1994-02-15 23:52 millert + + * CHANGES: updated + +1994-02-15 23:40 millert + + * sudo.h: took out Envp + +1994-02-14 12:28 millert + + * BUGS: Initial revision + +1994-02-10 14:29 millert + + * sudo.c, sudo.h, CHANGES: added SECURE_PATH + +1994-02-10 14:05 millert + + * sudo.h: added SECURE_PATH + +1994-02-10 13:50 millert + + * INSTALL: added sample.sudoers note + +1994-02-10 13:47 millert + + * sudoers: Initial revision + +1994-02-09 14:54 millert + + * find_path.c: fixed typo + +1994-02-08 23:06 millert + + * PORTING: took out SAVED_UID garbage + +1994-02-08 22:55 millert + + * INSTALL: mentioned HAL + +1994-02-08 22:50 millert + + * sudo.h: added HAL line + +1994-02-08 22:48 millert + + * insults.h: added HAL insults + +1994-02-08 22:48 millert + + * TODO: updated + +1994-02-08 22:02 millert + + * logging.c: more verbose error if mailer not found + +1994-02-08 22:02 millert + + * check.c: now do getpwent as root for soem shadow password systems + (bsdi) + +1994-02-08 13:22 millert + + * sudo.h: took out SAVED_UID garbade + +1994-02-08 13:21 millert + + * sudo.c: took out SAVED_UID garbage since it don't work + +1994-02-06 17:43 millert + + * README: updated + +1994-02-06 17:40 millert + + * insults.h: added a missing space :-) + +1994-02-05 19:48 millert + + * sudo.c, sudo.h: took out multimax cruft + +1994-02-05 19:30 millert + + * INSTALL: minor update + +1994-02-05 19:30 millert + + * PORTING: finished + +1994-02-05 19:19 millert + + * sudo.c: fixed a typo + indentation + +1994-02-05 18:43 millert + + * sudo.h: took outumoved some defines to the config file ,. ,. + +1994-02-05 15:17 millert + + * PORTING: Initial revision + +1994-02-05 15:17 millert + + * TODO: did #6 + +1994-02-05 15:16 millert + + * sudo.h: added HAS_SAVED_UID + +1994-02-05 15:16 millert + + * sudo.c: put back AIX cruft + +1994-02-03 00:44 millert + + * sudo.c: aix changes + +1994-02-02 01:31 millert + + * CHANGES: updated + +1994-02-02 01:30 millert + + * check.c, logging.c, parse.c, sudo.c, sudo.h: now is only root + when abs necesary + +1994-02-01 22:21 millert + + * check.c: added missing %s\n + +1994-01-31 02:06 millert + + * install-sh: Initial revision + +1994-01-31 01:58 millert + + * CHANGES, TODO: updated + +1994-01-31 01:56 millert + + * sudo.c: now removed _RLD_* for alphas + +1994-01-31 01:50 millert + + * INSTALL: updated for new config scheme + +1994-01-30 19:42 millert + + * find_path.c: more verbose eror messages + +1994-01-27 14:08 millert + + * TODO: now have solaris + +1994-01-27 14:07 millert + + * sudo.h: define __svr4__ for SOLARIS + +1994-01-27 14:07 millert + + * check.c: added svr4 junk for shadow pws for solaris 2.x + +1994-01-27 13:19 millert + + * check.c, sudo.c: took out setuid(0) and setreuid(udi) garbage. + Its not needed since we start out setuid with the correct perms. + +1994-01-26 19:51 millert + + * check.c, sudo.c, sudo.h: now use setreuid() + +1994-01-26 18:58 millert + + * sudo.man: revised AUTHORS secrtion & added ENV_EDITOR stuff to + VARIABLES sectoin + +1994-01-26 18:52 millert + + * visudo.c: now uses ENV_EDITOR if you want to use the EDITOR envar + +1994-01-26 18:52 millert + + * sudo.h: now uses ENV_EDITOR if you want to use the EDITOR envar + >> . + +1993-12-07 01:33 millert + + * README: minor update + spell fix + +1993-12-07 01:33 millert + + * INSTALL: rewrote most of this + +1993-12-07 01:13 millert + + * sudo.h: added all options that are in the Makefile + +1993-12-07 00:23 millert + + * getpass.c: now use USE_TERMIO #define for sgi & hpux + +1993-12-06 23:19 millert + + * TODO: todo: posix sigs + +1993-12-06 01:12 millert + + * check.c, find_path.c: always include strings.h + +1993-12-05 20:34 millert + + * visudo.c: added STATICEDITOR + +1993-12-05 20:30 millert + + * sudo.h: sgi has vi in /usr/bin too + +1993-12-05 20:23 millert + + * sudo.man: added VISUAL + +1993-12-02 22:20 millert + + * sudo.h: sue /usr/bin/vi on some systems + +1993-12-02 22:19 millert + + * sudo.c: fixed warning (include strings.h) + +1993-12-02 22:06 millert + + * sudo.man: added John_Rouillard@dl5000.bc.edu's changes (new + features) + +1993-12-02 21:38 millert + + * CHANGES: changes from John_Rouillard@dl5000.bc.edu + +1993-12-02 21:35 millert + + * visudo.c: added EDITOR envar + +1993-12-02 21:34 millert + + * check.c, find_path.c, parse.c, sudo.c: added patches from + John_Rouillard directory spec uses EDITOR + +1993-12-01 19:32 millert + + * getpass.c: added flush for hpux + +1993-11-30 13:37 millert + + * sudo.c: no longer assume malloc returns a char * + +1993-11-29 20:35 millert + + * sudo.c: alpha change to remove LD_-like thing fixed SHLIB_PATH + stuff -- now gets removed correctly + +1993-11-29 19:31 millert + + * sudo.h: added STD_HEADERS macro + +1993-11-29 19:14 millert + + * sudo.c: now uses STD_HEADERS macor for ansi + +1993-11-29 19:14 millert + + * find_path.c: now uses STD_HEADERS macro + +1993-11-29 19:13 millert + + * check.c: niceties for C compiler bitches -- no real change + +1993-11-29 13:04 millert + + * visudo.c: now doesn't fclose a file never opened. + +1993-11-28 16:35 millert + + * sudo.man: added visudo line + +1993-11-28 16:31 millert + + * sudo.man: added error stuff added me in there... + +1993-11-28 03:12 millert + + * CHANGES: noted insults + +1993-11-28 03:01 millert + + * INSTALL: added blurb about reading stuff + +1993-11-28 03:00 millert + + * sudo.h: added insults + +1993-11-28 03:00 millert + + * insults.h: corrected somments and removed newlines + +1993-11-28 03:00 millert + + * check.c: now uses insults + +1993-11-28 02:45 millert + + * insults.h: Initial revision + +1993-11-27 19:46 millert + + * INSTALL: added dec syslog note + +1993-11-27 19:25 millert + + * sample.sudoers: added real stuff in there + +1993-11-27 19:24 millert + + * TODO: added a todo + +1993-11-27 19:10 millert + + * TODO: added one + +1993-11-27 18:59 millert + + * sample.sudoers: Initial revision + +1993-11-27 18:59 millert + + * sudo.man: updated with changes + +1993-11-27 18:52 millert + + * sudo.man: Initial revision + +1993-11-27 18:48 millert + + * CHANGES, COPYING, INSTALL, README, TODO, indent.pro: Initial + revision + +1993-11-27 18:46 millert + + * visudo.c: updated version number and took out jeff's old addr + since it is no good + +1993-11-27 18:42 millert + + * sudo.h, check.c, find_path.c, logging.c, parse.c, parse.lex, + parse.yacc, sudo.c: updated version number and took out jeff's + email (since it is invalid) + +1993-10-28 09:36 millert + + * check.c: added fflush() + +1993-10-22 20:46 millert + + * find_path.c: now return NULL instead pfof exiting for + nopnn-fatal errors + +1993-10-21 16:57 millert + + * check.c: new banner + +1993-10-21 16:42 millert + + * parse.lex: now sudo.h gets included first + +1993-10-17 20:31 millert + + * parse.lex: now can use flex + +1993-10-17 20:31 millert + + * sudo.h: linux patch + +1993-10-17 20:30 millert + + * sudo.c: hpux 9 fix, removes SHLIB_PATH linux patch + +1993-10-17 20:30 millert + + * check.c: linux diff + +1993-10-15 16:03 millert + + * find_path.c: stat now ignores EINVAL + +1993-10-05 21:48 millert + + * find_path.c, sudo.c: now declare strdup as extern + +1993-10-04 15:23 millert + + * visudo.c: reformatted with indent + by hand + +1993-10-04 15:10 millert + + * check.c, find_path.c, getpass.c, logging.c, parse.c, sudo.c, + sudo.h: used indent to "fix" coding style + +1993-10-03 20:12 millert + + * find_path.c: now checks '.' or '.' or '' in PATH -- but does it + LAST should maybe move the code that does this into the loop + body. makes it messier tho. hmmm. + +1993-09-08 11:53 millert + + * find_path.c: redid the fix for non-executable files in an easier + to read way plus some minor aethetic changes + +1993-09-08 11:39 millert + + * find_path.c: fixed bug with non-executable tings of same name in + path introduced by checkig errno after stat(2). + +1993-09-05 10:02 millert + + * sudo.c: fixed off by one error + +1993-09-05 09:55 millert + + * find_path.c: now handles decending below '/' correctly + +1993-09-05 08:35 millert + + * sudo.c: now actually builds Envp instead of munging envp + +1993-09-04 15:42 millert + + * parse.yacc: now includes sys/param.h + +1993-09-04 15:41 millert + + * visudo.c: now includes sys/param.h + +1993-09-04 15:30 millert + + * sudo.h: fixed ifndef -> ifdef + +1993-09-04 15:19 millert + + * qualify.c: make more like find_path.c + +1993-09-04 15:18 millert + + * find_path.c: rewritten by millert + +1993-09-04 15:17 millert + + * sudo.h: fixed MAXCOMMANDLENGTH now uses USE_CWD and NEED_STRDUP + added info about new defines in the comment + +1993-09-04 15:15 millert + + * logging.c: now uses USE_CWD + +1993-09-04 14:10 millert + + * sudo.h: added delc for clean_envp() and Envp + +1993-09-04 14:09 millert + + * sudo.c: now rips LD_* env vars out of envp and passed sanitized + Envp to exec + +1993-09-04 14:09 millert + + * logging.c: now uses execve() + +1993-09-04 14:08 millert + + * find_path.c: ENOTDIR is ok now too (in case part of the path is + bogus) + +1993-09-04 08:17 millert + + * qualify.c: now works correctly (ttaltotal rewrite) + +1993-09-04 07:59 millert + + * parse.lex: now includes sys/param.h didn't match trailing / -- + fix from rouilj@cs.umb.edu + +1993-06-11 18:04 millert + + * sudo.c: moved around the #ifndef _AIX + +1993-06-11 18:03 millert + + * check.c, logging.c, parse.c: Initial revision + +1993-03-20 07:57 millert + + * qualify.c: Initial revision + +1993-03-13 15:09 millert + + * find_path.c: now works if you do sudo bin/test + +1993-03-13 14:20 millert + + * find_path.c: works + +1993-03-02 18:28 millert + + * sudo.h: Initial revision + +1993-03-02 11:35 millert + + * visudo.c: Initial revision + +1993-03-02 11:32 millert + + * parse.lex, parse.yacc: Initial revision + +1993-02-16 13:24 millert + + * sudo.c: took out errno.h + +1993-02-16 13:22 millert + + * sudo.c: now spews error if exec fails and exits with -1 + +1993-02-16 12:07 millert + + * sudo.c: Initial revision + +1993-02-15 22:27 millert + + * find_path.c: now only execs files with (an) executable bit set. + +1993-02-15 22:01 millert + + * find_path.c: Initial revision + +1993-02-15 14:32 millert + + * getpass.c: added nice comment + +1993-02-15 14:19 millert + + * getpass.c: now works on sgi's + +1993-02-15 13:57 millert + + * getpass.c: Initial revision + diff --git a/HISTORY b/HISTORY index 17d0b79..f9a12b2 100644 --- a/HISTORY +++ b/HISTORY @@ -1,47 +1,49 @@ -A Brief history of sudo(8): - -Sudo was first conceived and implemented by Bob Coggeshall and Cliff -Spencer around 1980 at the Department of Computer Science at -SUNY/Buffalo. It ran on a VAX-11/750 running 4.1BSD. An updated -version, credited to Phil Betchel, Cliff Spencer, Gretchen Phillips, -John LoVerso and Don Gworek, was posted to the net.sources newsgroup -in December of 1985. - -In the Summer of 1986, Garth Snyder released an enhanced version -of sudo. For the next 5 years, sudo was fed and watered by a handful -of folks at CU-Boulder, including Bob Coggeshall, Bob Manchek, and -Trent Hein. - -In 1991, Dave Hieb and Jeff Nieusma wrote a new version of sudo -with an enhanced sudoers format under contract to a consulting firm -called "The Root Group". This version was later released under the -GNU public license. - -In 1994, after maintaining sudo informally within CU-Boulder for -some time, Todd Miller made a public release of "CU sudo" (version -1.3) with bug fixes and support for more operating systems. The -"CU" was added to differentiate it from the "official" version from -"The Root Group". - -In 1996, Todd, who had been maintaining sudo for several years in -his spare time, brought sudo development under the umbrella of his -consulting firm, Courtesan Consulting. Courtesan remains committed -to a free sudo and is sponsoring another sudo rewrite as well as -continued development of the sudo 1.x code base. - -In 1999, the "CU" prefix was dropped from the name since there has -been no formal release of sudo from "The Root Group" since 1991 -(the original authors now work elsewhere). As of version 1.6, Sudo -no longer contains any of the original "Root Group" code and is -available under an ISC-style license. - -In 2004, Todd incorporated as GratiSoft, Inc. to provide commercial -support and enhancements to the sudo community. - -In 2005, GratiSoft was put on hold. +A brief history of sudo: + +Sudo was first conceived and implemented by Bob Coggeshall and Cliff Spencer +around 1980 at the Department of Computer Science at SUNY/Buffalo. It ran on +a VAX-11/750 running 4.1BSD. An updated version, credited to Phil Betchel, +Cliff Spencer, Gretchen Phillips, John LoVerso and Don Gworek, was posted to +the net.sources Usenet newsgroup in December of 1985. + +In the Summer of 1986, Garth Snyder released an enhanced version of sudo. +For the next 5 years, sudo was fed and watered by a handful of folks at +CU-Boulder, including Bob Coggeshall, Bob Manchek, and Trent Hein. + +In 1991, Dave Hieb and Jeff Nieusma wrote a new version of sudo with an +enhanced sudoers format under contract to a consulting firm called "The Root +Group". This version was later released under the GNU public license. + +In 1994, after maintaining sudo informally within CU-Boulder for some time, +Todd Miller made a public release of "CU sudo" (version 1.3) with bug fixes +and support for more operating systems. The "CU" was added to differentiate +it from the "official" version from "The Root Group". + +In 1995, a new parser for the sudoers file was contributed by Chris Jepeway. +The new parser was a proper grammar (unlike the old one) and could work with +both sudo and visudo (previously they had slightly different parsers). + +In 1996, Todd, who had been maintaining sudo for several years in his spare +time, moved distribution of sudo from a CU-Boulder ftp site to his domain, +courtesan.com. + +In 1999, the "CU" prefix was dropped from the name since there has been no +formal release of sudo from "The Root Group" since 1991 (the original +authors now work elsewhere). As of version 1.6, Sudo no longer contains any +of the original "Root Group" code and is available under an ISC-style +license. + +In 2001, the sudo web site, ftp site and mailing lists were moved from +courtesan.com to the sudo.ws domain (sudo.org was already taken). + +In 2005, Todd rewrote the sudoers parser to better support the features that +had been added in the past ten years. This new parser removes some +limitations of the previous one, removes ordering constraints and adds +support for including multiple sudoers files. sudo, in its current form, is maintained by: - Todd Miller + Todd Miller Todd continues to enhance sudo and fix bugs. + diff --git a/INSTALL b/INSTALL index 1692887..2ffb8f2 100644 --- a/INSTALL +++ b/INSTALL @@ -1,5 +1,5 @@ -Installation instructions for Sudo 1.6.9 -======================================== +Installation instructions for Sudo 1.7 +====================================== Sudo uses a `configure' script to probe the capabilities and type of the system in question. In this release, `configure' takes many @@ -189,6 +189,12 @@ Special features/options: this file instead of /etc/ldap.secret to read the secret password when rootbinddn is specified in the ldap config file. + --with-nsswitch[=filename] + Path to nsswitch.conf or "no" to disable nsswitch support. + If specified, sudo uses this file instead of /etc/nsswitch.conf. + If nsswitch is disabled but LDAP is enabled, sudo will check + LDAP first, then the sudoers file. + --with-aixauth Enable support for the AIX 4.x general authentication function. This will use the authentication scheme specified for the user @@ -200,7 +206,7 @@ Special features/options: Linux, Solaris and HP-UX (version 11 and higher). NOTE: on RedHat Linux and Fedora you *must* have an /etc/pam.d/sudo - file installed. You may either use the sample.pam file included with + file install. You may either use the sample.pam file included with sudo or use /etc/pam.d/su as a reference. The sample.pam file included with sudo may or may not work with other Linux distributions. On Solaris and HP-UX 11 systems you should check (and understand) @@ -228,10 +234,6 @@ Special features/options: unless the 'use_loginclass' option is defined in sudoers or the user specifies a class on the command line. - --with-project - Enable support for Solaris project resource limits. - This option is only available on Solaris 9 and above. - --with-bsdauth Enable support for BSD authentication. This is the default for BSD/OS and OpenBSD systems that support it. @@ -241,6 +243,10 @@ Special features/options: is supported. If you don't have /usr/include/bsd_auth.h then you cannot use this. + --with-project + Enable support for Solaris project resource limits. + This option is only available on Solaris 9 and above. + --with-noexec[=PATH] Enable support for the "noexec" functionality which prevents a dynamically-linked program being run by sudo from executing @@ -522,6 +528,13 @@ The following options are also configurable at runtime: option. visudo will then only use the VISUAL or EDITOR variables if they match a value specified via --with-editor. + --with-askpass=PATH + Set PATH as the "askpass" program to use when no tty is + available. Typically, this is a graphical password prompter, + similar to the one used by ssh. The program must take a + prompt as an argument and print the received password to + the standard output. + --disable-authentication By default, sudo requires the user to authenticate via a password or similar means. This options causes sudo to @@ -533,6 +546,13 @@ The following options are also configurable at runtime: "chaining" sudo commands to get a root shell by doing something like "sudo sudo /bin/sh". + --enable-gss-krb5-ccache-name + Use the gss_krb5_ccache_name() function to set the Kerberos + V credential cache file name. By default, sudo will use + the KRB5CCNAME environment variable to set this. While + gss_krb5_ccache_name() provides a better API to do this it + is not supported by all Kerberos V and SASL combinations. + --enable-log-host Log the hostname in the log file. @@ -702,6 +722,11 @@ HP-UX: noexec to work. Binary packages of gcc are available from http://hpux.connect.org.uk/ and http://hpux.cs.utah.edu/. + To prevent PAM from overriding the value of umask on HP-UX 11, + you will need to add a line like the following to /etc/pam.conf: + + sudo session required libpam_hpsec.so.1 bypass_umask + SunOS 4.x: The /bin/sh shipped with SunOS blows up while running configure. You can work around this by installalling bash or zsh. If you diff --git a/LICENSE b/LICENSE index 69266be..786b7a0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ Sudo is distributed under the following ISC-style license: - Copyright (c) 1994-1996,1998-2005 Todd C. Miller + Copyright (c) 1994-1996, 1998-2008 + 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 @@ -18,11 +19,11 @@ Sudo is distributed under the following ISC-style license: Agency (DARPA) and Air Force Research Laboratory, Air Force Materiel Command, USAF, under agreement number F39502-99-1-0512. -Additionally, fnmatch.c, fnmatch.h, getcwd.c, glob.c, glob.h, mkstemp.c -and snprintf.c bear the following UCB license: +Additionally, fnmatch.c, fnmatch.h, getcwd.c, glob.c, glob.h and snprintf.c +bear the following UCB license: Copyright (c) 1987, 1989, 1990, 1991, 1992, 1993, 1994 - The Regents of the University of California. All rights reserved. + The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/Makefile.in b/Makefile.in index 1650803..c097af7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,5 +1,6 @@ # -# Copyright (c) 1996, 1998-2007 Todd C. Miller +# Copyright (c) 1996, 1998-2005, 2007-2008 +# 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 @@ -20,21 +21,21 @@ # # @configure_input@ # -# $Sudo: Makefile.in,v 1.246.2.32 2008/06/22 20:29:03 millert Exp $ +# $Sudo: Makefile.in,v 1.326 2008/12/03 20:40:47 millert Exp $ # #### Start of system configuration section. #### srcdir = @srcdir@ +devdir = @devdir@ authdir = $(srcdir)/auth top_builddir = . -VPATH = @srcdir@ # Compiler & tools to use CC = @CC@ LEX = flex YACC = @YACC@ -NROFF = nroff +NROFF = nroff -Tascii LIBTOOL = @LIBTOOL@ # Our install program supports extra flags... @@ -61,11 +62,11 @@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ sysconfdir = @sysconfdir@ +libexecdir = @libexecdir@ +datarootdir = @datarootdir@ mandir = @mandir@ noexecfile = @NOEXECFILE@ noexecdir = @NOEXECDIR@ -libexecdir = @libexecdir@ -datarootdir = @datarootdir@ # Directory in which to install sudo. sudodir = $(bindir) @@ -93,7 +94,7 @@ sudoers_gid = @SUDOERS_GID@ sudoers_mode = @SUDOERS_MODE@ # Pass in paths and uid/gid + OS dependent defined -DEFS = @OSDEFS@ -D_PATH_SUDOERS=\"$(sudoersdir)/sudoers\" -D_PATH_SUDOERS_TMP=\"$(sudoersdir)/sudoers.tmp\" -DSUDOERS_UID=$(sudoers_uid) -DSUDOERS_GID=$(sudoers_gid) -DSUDOERS_MODE=$(sudoers_mode) +DEFS = @OSDEFS@ -D_PATH_SUDOERS=\"$(sudoersdir)/sudoers\" -DSUDOERS_UID=$(sudoers_uid) -DSUDOERS_GID=$(sudoers_gid) -DSUDOERS_MODE=$(sudoers_mode) #### End of system configuration section. #### @@ -101,60 +102,68 @@ SHELL = /bin/sh PROGS = @PROGS@ -SRCS = alloc.c alloca.c check.c closefrom.c def_data.c defaults.c env.c err.c \ - fileops.c find_path.c fnmatch.c getcwd.c getprogname.c getspwuid.c \ - gettime.c glob.c goodpath.c interfaces.c ldap.c lex.yy.c lsearch.c \ - logging.c memrchr.c mkstemp.c parse.c parse.lex parse.yacc set_perms.c \ - sigaction.c snprintf.c strcasecmp.c strerror.c strlcat.c strlcpy.c \ - sudo.c sudo_noexec.c sudo.tab.c sudo_edit.c testsudoers.c tgetpass.c \ - utimes.c visudo.c zero_bytes.c selinux.c sesh.c $(AUTH_SRCS) +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) 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 ins_2001.h ins_classic.h ins_csops.h \ - ins_goons.h insults.h interfaces.h logging.h parse.h sudo.h sudo.tab.h \ - version.h auth/sudo_auth.h emul/err.h emul/fnmatch.h emul/search.h \ - emul/utime.h emul/glob.h emul/timespec.h +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 AUTH_OBJS = sudo_auth.o @AUTH_OBJS@ -PARSEOBJS = sudo.tab.o lex.yy.o alloc.o defaults.o +# 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 -SUDOBJS = check.o env.o getspwuid.o gettime.o goodpath.o fileops.o find_path.o \ - interfaces.o logging.o parse.o set_perms.o sudo.o sudo_edit.o \ - tgetpass.o zero_bytes.o @SUDO_OBJS@ $(AUTH_OBJS) $(PARSEOBJS) +SUDO_OBJS = $(COMMON_OBJS) $(AUTH_OBJS) @SUDO_OBJS@ 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 -VISUDOBJS = visudo.o fileops.o gettime.o goodpath.o find_path.o $(PARSEOBJS) +VISUDO_OBJS = $(COMMON_OBJS) visudo.o fileops.o gettime.o goodpath.o \ + find_path.o pwutil.o -TESTOBJS = interfaces.o testsudoers.o $(PARSEOBJS) +TEST_OBJS = $(COMMON_OBJS) interfaces.o testsudoers.o tsgetgrpw.o tspwutil.o -LIBOBJS = @LIBOBJS@ @ALLOCA@ +LIB_OBJS = @LIBOBJS@ -VERSION = 1.6.9p17 +VERSION = 1.7.0 -DISTFILES = $(SRCS) $(HDRS) BUGS CHANGES HISTORY INSTALL INSTALL.configure \ - LICENSE Makefile.in PORTING README README.LDAP \ - TROUBLESHOOTING UPGRADE aclocal.m4 acsite.m4 aixcrypt.exp \ - config.guess config.h.in config.sub configure configure.in \ - def_data.in fnmatch.3 indent.pro install-sh ltmain.sh \ - mkdefaults mkinstalldirs pathnames.h.in sample.pam \ - sample.syslog.conf sample.sudoers schema.OpenLDAP \ - schema.iPlanet sudo.cat sudo.man.in sudo.pod sudoers \ - sudoers.cat sudoers.man.in sudoers.pod sudoers2ldif \ - visudo.cat visudo.man.in visudo.pod auth/API +DISTFILES = $(SRCS) $(HDRS) ChangeLog HISTORY INSTALL INSTALL.configure \ + LICENSE Makefile.in PORTING README README.LDAP TROUBLESHOOTING \ + UPGRADE WHATSNEW aclocal.m4 acsite.m4 aixcrypt.exp config.guess \ + config.h.in config.sub configure configure.in def_data.in \ + indent.pro install-sh ltmain.sh mkdefaults mkinstalldirs \ + pathnames.h.in sample.pam sample.syslog.conf sample.sudoers \ + schema.ActiveDirectory schema.OpenLDAP schema.iPlanet sudo.cat \ + sudo.man.in sudo.pod sudo.psf sudo_usage.h.in sudoers sudoers.cat \ + sudoers.man.in sudoers.pod sudoers.ldap.cat sudoers.ldap.man.in \ + sudoers.ldap.pod sudoers2ldif visudo.cat visudo.man.in visudo.pod \ + auth/API -BINFILES= BUGS CHANGES HISTORY LICENSE README TROUBLESHOOTING \ +BINFILES= ChangeLog HISTORY LICENSE README TROUBLESHOOTING \ UPGRADE install-sh mkinstalldirs sample.syslog.conf sample.sudoers \ sudo sudo.cat sudo.man sudo.pod sudoers sudoers.cat sudoers.man \ sudoers.pod visudo visudo.cat visudo.man visudo.pod -BINSPECIAL= INSTALL.binary Makefile.binary libtool +BINSPECIAL= INSTALL.binary Makefile.binary.in libtool SUDODEP = $(srcdir)/sudo.h $(srcdir)/compat.h $(srcdir)/defaults.h \ - $(srcdir)/logging.h config.h def_data.h pathnames.h + $(srcdir)/error.h $(srcdir)/list.h $(srcdir)/logging.h \ + $(srcdir)/sudo_nss.h $(devdir)/def_data.h pathnames.h config.h AUTHDEP = $(SUDODEP) $(authdir)/sudo_auth.h @@ -163,7 +172,7 @@ INSDEP = $(srcdir)/ins_2001.h $(srcdir)/ins_classic.h $(srcdir)/ins_csops.h \ all: $(PROGS) -.SUFFIXES: .o .c .h .lex .yacc .man .cat .lo +.SUFFIXES: .o .c .h .l .y .man .cat .lo .c.o: $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $< @@ -173,16 +182,16 @@ all: $(PROGS) .man.cat: @rm -f $(srcdir)/$@ - $(NROFF) -man $< > $(srcdir)/$@ + sed '1s/^/.if n .ll 78n/' $< | $(NROFF) -man > $(srcdir)/$@ -sudo: $(SUDOBJS) $(LIBOBJS) - $(CC) -o $@ $(SUDOBJS) $(LIBOBJS) $(SUDO_LDFLAGS) $(SUDO_LIBS) +sudo: $(SUDO_OBJS) $(LIB_OBJS) + $(CC) -o $@ $(SUDO_OBJS) $(LIB_OBJS) $(SUDO_LDFLAGS) $(SUDO_LIBS) -visudo: $(VISUDOBJS) $(LIBOBJS) - $(CC) -o $@ $(VISUDOBJS) $(LIBOBJS) $(LDFLAGS) $(LIBS) $(NET_LIBS) +visudo: $(VISUDO_OBJS) $(LIB_OBJS) + $(CC) -o $@ $(VISUDO_OBJS) $(LIB_OBJS) $(LDFLAGS) $(LIBS) $(NET_LIBS) -testsudoers: $(TESTOBJS) $(LIBOBJS) - $(CC) -o $@ $(TESTOBJS) $(LIBOBJS) $(LDFLAGS) $(LIBS) $(NET_LIBS) +testsudoers: $(TEST_OBJS) $(LIB_OBJS) + $(CC) -o $@ $(TEST_OBJS) $(LIB_OBJS) $(LDFLAGS) $(LIBS) $(NET_LIBS) sudo_noexec.lo: $(srcdir)/sudo_noexec.c $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_noexec.c @@ -191,61 +200,129 @@ sudo_noexec.la: sudo_noexec.lo $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ sudo_noexec.lo -avoid-version -rpath $(noexecdir) # Uncomment the following if you want "make distclean" to clean the parser -@DEV@PARSESRCS = sudo.tab.h sudo.tab.c lex.yy.c def_data.c def_data.h +@DEV@GENERATED = gram.h gram.c toke.c def_data.c def_data.h -# Uncomment the following if you intend to modify parse.yacc -@DEV@sudo.tab.c sudo.tab.h: parse.yacc -@DEV@ rm -f sudo.tab.h sudo.tab.c -@DEV@ $(YACC) -d -b sudo $(srcdir)/parse.yacc +# Uncomment the lines before -@true if you intend to modify gram.y +$(devdir)/gram.c: $(srcdir)/gram.y +@DEV@ $(YACC) -d $(srcdir)/gram.y +@DEV@ mv -f y.tab.c gram.c +@DEV@ if cmp -s y.tab.h gram.h; then rm -f y.tab.h; else mv -f y.tab.h gram.h; fi + -@true -# Uncomment the following if you intend to modify parse.lex -@DEV@lex.yy.c: parse.lex -@DEV@ rm -f lex.yy.c -@DEV@ $(LEX) $(srcdir)/parse.lex +# Uncomment the lines before -@true if you intend to modify toke.l +$(devdir)/toke.c: $(srcdir)/toke.l +@DEV@ $(LEX) $(srcdir)/toke.l +@DEV@ mv -f lex.yy.c toke.c + -@true # Uncomment the following if you intend to modify def_data.in -@DEV@def_data.h def_data.c: def_data.in +@DEV@$(devdir)/def_data.h $(devdir)/def_data.c: $(srcdir)/def_data.in @DEV@ perl $(srcdir)/mkdefaults -o def_data $(srcdir)/def_data.in # Dependencies (not counting auth functions) -alloc.o: alloc.c $(SUDODEP) -check.o: check.c $(SUDODEP) -closefrom.o: closefrom.c config.h -env.o: env.c $(SUDODEP) -err.o: err.c config.h compat.h emul/err.h -fileops.o: fileops.c $(SUDODEP) -find_path.o: find_path.c $(SUDODEP) -getprogname.o: getprogname.c config.h -getspwuid.o: getspwuid.c $(SUDODEP) -goodpath.o: goodpath.c $(SUDODEP) -logging.o: logging.c $(SUDODEP) -set_perms.o: set_perms.c $(SUDODEP) -tgetpass.o: tgetpass.c $(SUDODEP) -visudo.o: visudo.c $(SUDODEP) version.h -sudo.o: sudo.c $(SUDODEP) interfaces.h version.h -interfaces.o: interfaces.c $(SUDODEP) interfaces.h -testsudoers.o: testsudoers.c $(SUDODEP) parse.h interfaces.h -parse.o: parse.c $(SUDODEP) parse.h interfaces.h -lex.yy.o: lex.yy.c $(SUDODEP) parse.h sudo.tab.h -sudo.tab.o: sudo.tab.c $(SUDODEP) parse.h sudo.tab.c sudo.tab.h -defaults.o: defaults.c $(SUDODEP) def_data.c auth/sudo_auth.h -fnmatch.o: fnmatch.c config.h compat.h emul/fnmatch.h -getcwd.o: getcwd.c config.h compat.h -glob.o: glob.c config.h compat.h emul/glob.h -lsearch.o: lsearch.c config.h compat.h emul/search.h -memrchr.o: memrchr.c config.h compat.h -mkstemp.o: mkstemp.c config.h compat.h -selinux.o: selinux.c $(SUDODEP) -snprintf.o: snprintf.c config.h compat.h -strcasecmp.o: strcasecmp.c config.h -strlcat.o: strlcat.c config.h -strlcpy.o: strlcpy.c config.h -strerror.o: strerror.c config.h -utime.o: utime.c config.h pathnames.h compat.h emul/utime.h -ldap.o: ldap.c $(SUDODEP) parse.h -sudo_edit.o: sudo_edit.c $(SUDODEP) - -# Authentication functions live in "auth" dir and so need extra care +aix.o: $(srcdir)/aix.c + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/aix.c +alias.o: $(srcdir)/alias.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/redblack.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alias.c +alloc.o: $(srcdir)/alloc.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alloc.c +check.o: $(srcdir)/check.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/check.c +closefrom.o: $(srcdir)/closefrom.c config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/closefrom.c +defaults.o: $(srcdir)/defaults.c $(SUDODEP) $(srcdir)/def_data.c $(authdir)/sudo_auth.h $(devdir)/gram.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/defaults.c +env.o: $(srcdir)/env.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/env.c +error.o: $(srcdir)/error.c $(srcdir)/compat.h $(srcdir)/error.h config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/error.c +fileops.o: $(srcdir)/fileops.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/fileops.c +find_path.o: $(srcdir)/find_path.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/find_path.c +fnmatch.o: $(srcdir)/fnmatch.c $(srcdir)/emul/fnmatch.h $(srcdir)/compat.h config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/fnmatch.c +getcwd.o: $(srcdir)/getcwd.c $(srcdir)/compat.h config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/getcwd.c +getprogname.o: $(srcdir)/getprogname.c config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/getprogname.c +getspwuid.o: $(srcdir)/getspwuid.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/getspwuid.c +gettime.o: $(srcdir)/gettime.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/gettime.c +glob.o: $(srcdir)/glob.c $(srcdir)/emul/glob.h $(srcdir)/compat.h config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/glob.c +goodpath.o: $(srcdir)/goodpath.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/goodpath.c +gram.o: $(devdir)/gram.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(devdir)/gram.c +interfaces.o: $(srcdir)/interfaces.c $(SUDODEP) $(srcdir)/interfaces.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/interfaces.c +isblank.o: $(srcdir)/isblank.c $(srcdir)/compat.h config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/isblank.c +lbuf.o: $(srcdir)/lbuf.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/lbuf.c +ldap.o: $(srcdir)/ldap.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/ldap.c +list.o: $(srcdir)/list.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/list.c +logging.o: $(srcdir)/logging.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/logging.c +match.o: $(srcdir)/match.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/interfaces.h $(devdir)/gram.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/match.c +memrchr.o: $(srcdir)/memrchr.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/memrchr.c +mkstemp.o: $(srcdir)/mkstemp.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/mkstemp.c +parse.o: $(srcdir)/parse.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/parse.c +pwutil.o: $(srcdir)/pwutil.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/pwutil.c +redblack.o: $(srcdir)/redblack.c $(SUDODEP) $(srcdir)/redblack.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/redblack.c +set_perms.o: $(srcdir)/set_perms.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/set_perms.c +sigaction.o: $(srcdir)/sigaction.c $(srcdir)/compat.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sigaction.c +snprintf.o: $(srcdir)/snprintf.c $(srcdir)/compat.h config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/snprintf.c +strcasecmp.o: $(srcdir)/strcasecmp.c $(srcdir)/compat.h config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strcasecmp.c +strerror.o: $(srcdir)/strerror.c $(srcdir)/compat.h config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strerror.c +strlcat.o: $(srcdir)/strlcat.c $(srcdir)/compat.h config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strlcat.c +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 + $(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 +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 +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) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/tgetpass.c +toke.o: $(devdir)/toke.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(devdir)/toke.c +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 + $(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 + +# Private copy of pwutil.o with MYPW defined for testsudoers +tspwutil.o: $(srcdir)/pwutil.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) -DMYPW -o tspwutil.o $(srcdir)/pwutil.c + sudo_auth.o: $(authdir)/sudo_auth.c $(AUTHDEP) $(INSDEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/sudo_auth.c afs.o: $(authdir)/afs.c $(AUTHDEP) @@ -304,6 +381,24 @@ sudoers.man:: sudoers.man.in 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)/" >> $@ ) + +sudoers.ldap.man:: sudoers.ldap.man.in + CONFIG_FILES=$@ CONFIG_HEADERS= sh ./config.status + +sudoers.ldap.cat: sudoers.ldap.man + +@DEV@HISTORY: history.pod +@DEV@ pod2text -l -i0 $> > $@ +@DEV@ +@DEV@LICENSE: license.pod +@DEV@ pod2text -l -i0 $> | sed '1,2d' > $@ + +ChangeLog: + cvs2cl --follow-only trunk + install: install-dirs install-binaries @INSTALL_NOEXEC@ install-sudoers install-man install-dirs: @@ -333,27 +428,22 @@ install-man: ln $(DESTDIR)$(mandirsu)/sudo.$(mansectsu) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu) $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/visudo.$(mantype) $(DESTDIR)$(mandirsu)/visudo.$(mansectsu) $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudoers.$(mantype) $(DESTDIR)$(mandirform)/sudoers.$(mansectform) + @LDAP@$(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudoers.ldap.$(mantype) $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform) @MAN_POSTINSTALL@ check: @echo nothing to check -tags: $(SRCS) - ctags $(SRCS) - -TAGS: $(SRCS) - etags $(SRCS) - clean: - -rm -f *.o $(PROGS) testsudoers core sudo.core visudo.core \ - testsudoers.core + -rm -f *.o *.lo stamp-* $(PROGS) testsudoers core *.core core.* mostlyclean: clean distclean: clean -rm -rf Makefile pathnames.h config.h config.status config.cache \ - config.log libtool sudo_noexec.lo .libs $(PARSESRCS) \ - sudo.man sudoers.man visudo.man + config.log libtool sudo_noexec.lo .libs $(GENERATED) \ + sudo.man sudoers.man sudoers.ldap.man visudo.man sudo_usage.h \ + Makefile.binary clobber: distclean @@ -394,9 +484,43 @@ bindist: fi ; \ cp $(srcdir)/INSTALL.binary $$tdir/INSTALL ; \ sh ./config.status --file=Makefile.binary && cp Makefile.binary $$tdir/Makefile ; \ - strip sudo ; \ - strip visudo ; \ + strip $$tdir/sudo ; \ + strip $$tdir/visudo ; \ cd tmp.$$ARCH && tar Ocf ../sudo-$(VERSION)-$$ARCH.tar sudo-$(VERSION) && cd .. ; \ - gzip --best sudo-$(VERSION)-$$ARCH.tar ; \ + gzip -f --best sudo-$(VERSION)-$$ARCH.tar ; \ rm -rf tmp.$$ARCH ; \ ) + +depot: + ( \ + tdir=tmp.depot ; \ + mkdir $$tdir ; \ + for i in sudo visudo sudo.man visudo.man sudoers.man sudoers ChangeLog HISTORY LICENSE README TROUBLESHOOTING UPGRADE sample.syslog.conf sample.sudoers; do \ + if [ -f $$i ]; then \ + cp $$i $$tdir ; \ + elif [ -f $(srcdir)/$$i ]; then \ + cp $(srcdir)/$$i $$tdir ; \ + else \ + echo cannot find $$i ; \ + exit 1 ; \ + fi ; \ + done ; \ + if [ -f sudo_noexec.la ]; then \ + cp libtool $$tdir ; \ + $(LIBTOOL) --mode=install $(INSTALL) sudo_noexec.la `pwd`/$$tdir ; \ + fi ; \ + sed 's/@VERSION@/$(VERSION)/g' <$(srcdir)/sudo.psf >$$tdir/sudo.psf ; \ + printf '#!/sbin/sh\nrm -f /usr/local/bin/sudoedit\nln /usr/local/bin/sudo /usr/local/bin/sudoedit\n' > $$tdir/sudo-exec.postinstall ; \ + printf '#!/sbin/sh\nrm -f /usr/local/man/man1m/sudoedit.1m\nln /usr/local/man/man1m/sudo.1m /usr/local/man/man1m/sudoedit.1m\n' > $$tdir/sudo-man.postinstall ; \ + printf '#!/sbin/sh\nif [ ! -s /etc/sudoers ]; then\n\techo installing /usr/local/doc/sudo/sudoers as /etc/sudoers\n\techo use /usr/local/sbin/visudo to configure sudo\n\tcp /usr/local/doc/sudo/sudoers /etc/sudoers\n\tchmod 440 /etc/sudoers\n\tchown root:root /etc/sudoers\nfi\n' > $$tdir/sudo-config.postinstall ; \ + chmod 755 $$tdir/sudo-exec.postinstall $$tdir/sudo-man.postinstall $$tdir/sudo-config.postinstall ; \ + strip $$tdir/sudo ; \ + strip $$tdir/visudo ; \ + cd $$tdir ; \ + swpackage -x target_type=tape -d ../sudo-$(VERSION).depot -s sudo.psf ; \ + cd .. ; \ + gzip -f --best sudo-$(VERSION).depot; \ + rm -rf tmp.depot ; \ + ) + +.PHONY: ChangeLog diff --git a/README b/README index 4986b56..301ca55 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Sudo version 1.6.9 +This is Sudo version 1.7.0 The sudo philosophy =================== @@ -80,15 +80,14 @@ for the appropriate links. Web page ======== -There is a sudo `web page' at http://www.sudo.ws/sudo/ -that contains an overview of sudo as well as pointers to BETA versions -and other useful info. +There is a sudo web page at http://www.sudo.ws/sudo/ that contains +an overview of sudo, documentation, downloads, information about +beta versions and other useful info. Bug reports =========== -A list of known bugs may be found in the `BUGS' file. If you have -found what you believe to be a bug, you can file a bug report with -the sudo bug database, on at web at http://www.sudo.ws/bugs/. +If you have found what you believe to be a bug, you can file a bug +report with the sudo bug database, on at web at http://www.sudo.ws/bugs/. Please read over the `TROUBLESHOOTING' file *before* submitting a bug report. When reporting bugs, please be sure to include the diff --git a/README.LDAP b/README.LDAP index df4ad21..85f05f5 100644 --- a/README.LDAP +++ b/README.LDAP @@ -1,16 +1,27 @@ -This file explains how to use the optional LDAP functionality of SUDO to +This file explains how to build the optional LDAP functionality of SUDO to store /etc/sudoers information. This feature is distinct from LDAP passwords. +For general sudo LDAP configuration details, see the sudoers.ldap manual that +comes with the sudo distribution. A pre-formatted version of the manual may +be found in the sudoers.ldap.cat file. + +The sudo binary compiled with LDAP support should be totally backward +compatible and be syntactically and source code equivalent to its +non LDAP-enabled build. + LDAP philosophy =============== As times change and servers become cheap, an enterprise can easily have 500+ UNIX servers. Using LDAP to synchronize Users, Groups, Hosts, Mounts, and others across an enterprise can greatly reduce the administrative overhead. -Sudo in the past has only used a single local configuration file /etc/sudoers. -Some have attempted to workaround this by synchronizing changes via -RCS/CVS/RSYNC/RDIST/RCP/SCP and even NFS. Many have asked for a Hesiod, NIS, -or LDAP patch for sudo, so here is my attempt at LDAP'izing sudo. +In the past, sudo has used a single local configuration file, /etc/sudoers. +While the same sudoers file can be shared among machines, no built-in +mechanism exists to distribute it. Some have attempted to workaround this +by synchronizing changes via CVS/RSYNC/RDIST/RCP/SCP and even NFS. + +By using LDAP for sudoers we gain a centrally administered, globally +available configuration source for sudo. For information on OpenLDAP, please see http://www.openldap.org/. @@ -22,75 +33,6 @@ server, structure and contents. Many times 'options' are used in this document to refer to sudoer 'defaults'. They are one and the same. -Design Features -=============== - - * Sudo no longer needs to read sudoers in its entirety. Parsing of - /etc/sudoers requires the entire file to be read. The LDAP feature of sudo - uses two (sometimes three) LDAP queries per invocation. It never reads all - the sudoer entries in the LDAP store. This makes it especially fast and - particularly usable in LDAP environments. The first query is to parse - default options (see below). The second is to match against the username or - groups a user belongs to. (The special ALL tag is matched in this query - too.) If no match is made against the username, the third query pulls the - entries that match against user netgroups to compare back to the user. - - * Sudo no longer blows up if there is a typo. Parsing of /etc/sudoers can - still blow up when sudo is invoked. However when using the LDAP feature of - sudo, LDAP syntax rules are applied before the data is uploaded into the - LDAP server, so proper syntax is always guaranteed! One can of course still - insert a bogus hostname or username, but sudo will not care. - - * Options inside of entries now override global default options. - /etc/sudoers allowed for only default options and limited options associated - with user/host/command aliases. The syntax can be difficult for the newbie. - The LDAP feature attempts to simplify this and yet still provide maximum - flexibility. - - Sudo first looks for an entry called 'cn=default' in the SUDOers container. - If found, the multi-valued sudoOption attribute is parsed the same way the - global 'Defaults' line in /etc/sudoers is parsed. - - If on the second or third query, a response contains a sudoRole which - matches against the user, host, and command, then the matched object is - scanned for a additional options to override the top-level defaults. See - the example LDAP content below for more information. - - * Visudo is no longer needed. Visudo provides locking and syntax checking - against the /etc/sudoers file. Since LDAP updates are atomic, locking is no - longer necessary. Because syntax is checked when the data is inserted into - LDAP, the sudoers syntax check becomes unnecessary. - - * Aliases are no longer needed. User, Host, and Command Aliases were setup - to allow simplification and readability of the sudoers files. Since the - LDAP sudoer entry allows multiple values for each of its attributes and - since most LDAP browsers are graphical and easy to work with, original - aliases are no longer needed. - - If you want to specify lots of users into an entry or want to have similar - entries with identical users, then use either groups or user netgroups. - Thats what groups and netgroups are for and Sudo handles this well. - Alternately, one can just paste them all into the LDAP record. - - If you want to specify lots of hosts into an entry, use netgroups or IP - address matches (10.2.3.4/255.255.0.0). Thats what netgroups are for and - Sudo handles this well. Or just past them all into the LDAP record. - - If you want to specify lots of commands, use directories or wildcards, or - just paste them all into LDAP. That's what it's for. - - * The /etc/sudoers file can be disabled. Paranoid security administrators - can now disallow parsing of any local /etc/sudoers file by an LDAP - sudoOption 'ignore_local_sudoers'. This way all sudoers can be controlled - and audited in one place because local entries are not allowed. - In fact, if this option is included in the cn=defaults object of LDAP, - sudo won't even look for a /etc/sudoers file. - - * The sudo binary compiled with LDAP support should be totally backward - compatible and be syntactically and source code equivalent to its non - LDAP-enabled build. - - Build instructions ================== The most simplest way to build sudo with LDAP support is to include the @@ -103,33 +45,56 @@ to specify them at configure time. E.g. $ ./configure --with-ldap=/usr/local/ldapsdk -Sudo is developed using OpenLDAP. Other LDAP implementations may -require adding '-lldif' to SUDO_LIBS in the Makefile. +Sudo is developed using OpenLDAP but Netscape-based LDAP libraries +(such as those present in Solaris) are also known to work. Your Mileage may vary. Please let the sudo workers mailing list - know what combinations worked best for your -OS and LDAP Combinations so we can improve sudo. - -More Build Notes: -HP-UX 11.23 (gcc3) Galen Johnson - CFLAGS="-D__10_10_compat_code" LDFLAGS="-L/opt/ldapux/lib" + know if special configuration was required +to build an LDAP-enabled sudo so we can improve sudo. Schema Changes ============== -Add the appropriate schema to your LDAP server so that it may contain -sudoers content. +You must add the appropriate schema to your LDAP server before it +can store sudoers content. + +For OpenLDAP, copy the file schema.OpenLDAP to the schema directory +(e.g. /etc/openldap/schema). You must then edit your slapd.conf and +add an include line the new schema, e.g. + + # Sudo LDAP schema + include /etc/openldap/schema/sudo.schema + +In order for sudoRole LDAP queries to be efficient, the server must index +the attribute 'sudoUser', e.g. + + # Indices to maintain + index sudoUser eq + +After making the changes to slapd.conf, restart slapd. -For OpenLDAP, simply copy schema.OpenLDAP to the schema directory -(e.g. /etc/openldap/schema) and 'include' it in your slapd.conf and -restart slapd. For other LDAP servers, provide this to your LDAP -Administrator. Make sure to index the attribute 'sudoUser'. +For Netscape-derived LDAP servers such as SunONE, iPlanet or Fedora Directory, +copy the schema.iPlanet file to the schema directory with the name 99sudo.ldif. -For netscape-derived LDAP servers such as SunONE, iPlanet or Fedora -Directory, use the schema.iPlanet file. +On Solaris, schemas are stored in /var/Sun/mps/slapd-`hostname`/config/schema/. +For Fedora Directory Server, they are stored in /etc/dirsrv/schema/. -Importing /etc/sudoers to LDAP -============================== -Importing is a two step process. +After copying the schema file to the appropriate directory, restart +the LDAP server. + +Finally, using an LDAP browser/editor, enable indexing by editing the +client profile to provide a Service Search Descriptor (SSD) for sudoers, +replacing example.com with your domain: + + serviceSearchDescriptor: sudoers: ou=sudoers,dc=example,dc=com + +If using an Active Directory server, copy schema.ActiveDirectory +to your Windows domain controller and run the following command: + + ldifde -i -f schema.ActiveDirectory -c dc=X dc=example,dc=com + +Importing /etc/sudoers into LDAP +================================ +Importing sudoers is a two-step process. Step 1: Ask your LDAP Administrator where to create the ou=SUDOers container. @@ -150,28 +115,12 @@ options. # ./sudoers2ldif /etc/sudoers > /tmp/sudoers.ldif Step 2: -Import into your directory server. If you are using OpenLDAP, do the following -if you are using another directory, provide the LDIF file to your LDAP -Administrator. An example is shown below. +Import into your directory server. The following example is for +OpenLDAP. If you are using another directory, provide the LDIF +file to your LDAP Administrator. # ldapadd -f /tmp/sudoers.ldif -h ldapserver \ - > -D cn=Manager,dc=example,dc=com -W -x - -Example sudoers Entries in LDAP -=============================== -The equivalent of a sudoer in LDAP is a 'sudoRole'. It contains sudoUser(s), -sudoHost, sudoCommand and optional sudoOption(s) and sudoRunAs(s). - -The following example allows users in group wheel to run any -command on any host through sudo: - -dn: cn=%wheel,ou=SUDOers,dc=example,dc=com -objectClass: top -objectClass: sudoRole -cn: %wheel -sudoUser: %wheel -sudoHost: ALL -sudoCommand: ALL + -D cn=Manager,dc=example,dc=com -W -x Managing LDAP entries ===================== @@ -198,168 +147,32 @@ I recommend using any of the following LDAP browsers to administer your SUDOers. There are dozens of others, some Open Source, some free, some not. - -Configure your /etc/ldap.conf -============================= +Configure your /etc/ldap.conf and /etc/nsswitch.conf +==================================================== The /etc/ldap.conf file is meant to be shared between sudo, pam_ldap, nss_ldap and other ldap applications and modules. IBM Secureway unfortunately uses the same filename but has a different syntax. If you need to rename where this file is stored, re-run configure with the --with-ldap-conf-file=filename option. -Make sure you sudoers_base matches exactly with the location you specified -when you imported the sudoers. Below is an example /etc/ldap.conf - - # Either specify one or more URIs or one or more host:port pairs. - # If neither is specified sudo will default to localhost, port 389. - # - #host ldapserver - #host ldapserver1 ldapserver2:390 - # - # Default port if host is specified without one, defaults to 389. - #port 389 - # - # URI will override the host and port settings. - uri ldap://ldapserver - #uri ldaps://secureldapserver - #uri ldaps://secureldapserver ldap://ldapserver - # - # The amount of time, in seconds, to wait while trying to connect to - # an LDAP server. - bind_timelimit 30 - # - # The amount of time, in seconds, to wait while performing an LDAP query. - timelimit 30 - # - # must be set or sudo will ignore LDAP - sudoers_base ou=SUDOers,dc=example,dc=com - # - # verbose sudoers matching from ldap - #sudoers_debug 2 - # - # optional proxy credentials - #binddn - #bindpw - #rootbinddn - # - # LDAP protocol version, defaults to 3 - #ldap_version 3 - # - # Define if you want to use an encrypted LDAP connection. - # Typically, you must also set the port to 636 (ldaps). - #ssl on - # - # Define if you want to use port 389 and switch to - # encryption before the bind credentials are sent. - # Only supported by LDAP servers that support the start_tls - # extension such as OpenLDAP. - #ssl start_tls - # - # Additional TLS options follow that allow tweaking of the - # SSL/TLS connection. - # - #tls_checkpeer yes # verify server SSL certificate - #tls_checkpeer no # ignore server SSL certificate - # - # If you enable tls_checkpeer, specify either tls_cacertfile - # or tls_cacertdir. Only supported when using OpenLDAP. - # - #tls_cacertfile /etc/certs/trusted_signers.pem - #tls_cacertdir /etc/certs - # - # For systems that don't have /dev/random - # use this along with PRNGD or EGD.pl to seed the - # random number pool to generate cryptographic session keys. - # Only supported when using OpenLDAP. - # - #tls_randfile /etc/egd-pool - # - # You may restrict which ciphers are used. Consult your SSL - # documentation for which options go here. - # Only supported when using OpenLDAP. - # - #tls_ciphers - # - # Sudo can provide a client certificate when communicating to - # the LDAP server. - # Tips: - # * Enable both lines at the same time. - # * Do not password protect the key file. - # * Ensure the keyfile is only readable by root. - # - # For OpenLDAP: - #tls_cert /etc/certs/client_cert.pem - #tls_key /etc/certs/client_key.pem - # - # For 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 +See the "Configuring ldap.conf" section in the sudoers.ldap manual +for a list of supported ldap.conf parameters and an example ldap.conf + +Make sure you sudoers_base matches the location you specified when you +imported the sudoers ldif data. + +After configuring /etc/ldap.conf, you must add a line in /etc/nsswitch.conf +to tell sudo to look in LDAP for sudoers. See the "Configuring nsswitch.conf" +section in the sudoers.ldap manual for details. Note that sudo will use +/etc/nsswitch.conf even if the underlying operating system does not support it. +To disable nsswitch support, run configure with the --with-nsswitch=no option. +This will cause sudo to consult LDAP first and /etc/sudoers second, unless the +ignore_sudoers_file flag is set in the global LDAP options. Debugging your LDAP configuration ================================= Enable debugging if you believe sudo is not parsing LDAP the way you think it -it should. A value of 1 shows moderate debugging. A value of 2 shows the -results of the matches themselves. Make sure to set the value back to zero -so that other users don't get confused by the debugging messages. This value -is 'sudoers_debug' in the /etc/ldap.conf. - -Parsing Differences between /etc/sudoers and LDAP -================================================= -There are some subtle differences in the way sudoers is handled once in LDAP. -Probably the biggest is that according to the RFC, LDAP's ordering is -arbitrary and you cannot expect that Attributes & Entries are returned in -any order. If there are conflicting command rules on an entry, the negative -takes precedence. This is called paranoid behavior (not necessarily the -most specific match). - -Here is an example: - - # /etc/sudoers: - # Allow all commands except shell - johnny ALL=(root) ALL,!/bin/sh - # Always allows all commands because ALL is matched last - puddles ALL=(root) !/bin/sh,ALL - - # LDAP equivalent of Johnny - # Allows all commands except shell - dn: cn=role1,ou=Sudoers,dc=my-domain,dc=com - objectClass: sudoRole - objectClass: top - cn: role1 - sudoUser: johnny - sudoHost: ALL - sudoCommand: ALL - sudoCommand: !/bin/sh - - # LDAP equivalent of Puddles - # Notice that even though ALL comes last, it still behaves like - # role1 since the LDAP code assumes the more paranoid configuration - dn: cn=role2,ou=Sudoers,dc=my-domain,dc=com - objectClass: sudoRole - objectClass: top - cn: role2 - sudoUser: puddles - sudoHost: ALL - sudoCommand: !/bin/sh - sudoCommand: ALL - -Another difference is that negations on the Host, User or Runas are -currently ignorred. For example, these attributes do not work how -they first seem. - - # does not match all but joe - # rather, does not match anyone - sudoUser: !joe - - # does not match all but joe - # rather, matches everyone including Joe - sudoUser: ALL - sudoUser: !joe - - # does not match all but web01 - # rather, matches all hosts including web01 - sudoHost: ALL - sudoHost: !web01 +should. Setting the 'sudoers_debug' parameter to a value of 1 shows moderate +debugging. A value of 2 shows the results of the matches themselves. Make +sure to set the value back to zero so that other users don't get confused by +the debugging messages. diff --git a/TROUBLESHOOTING b/TROUBLESHOOTING index 4bf571b..a90b5eb 100644 --- a/TROUBLESHOOTING +++ b/TROUBLESHOOTING @@ -158,9 +158,12 @@ A) "cd" is a shell built-in command, you can't run it as a command Q) When I try to use "cd" with sudo the command completes without errors but nothing happens. -A) Some SVR4-derived OS's include a /usr/bin/cd command for reasons - unfathomable. A "cd" command is totally useless since a child process - cannot affect the current working directory of the parent (your shell). +A) Even though "cd" is a shell built-in command, some operating systems + include a /usr/bin/cd command for some reason. A standalone + "cd" command is totally useless since a child process (cd) cannot + affect the current working directory of the parent (your shell). + Thus, "sudo cd /foo" will start a child process, change the + directory and immediately exit without doing anything useful. Q) When I run sudo it says I am not allowed to run the command as root but I don't want to run it as root, I want to run it as another user. diff --git a/UPGRADE b/UPGRADE index 5d8591f..86e646f 100644 --- a/UPGRADE +++ b/UPGRADE @@ -1,6 +1,33 @@ Notes on upgrading from an older release ======================================== +o Upgrading from a version prior to 1.7.0: + + Starting with sudo 1.7.0 comments in the sudoers file must not + have a digit or minus sign immediately after the comment character + ('#'). Otherwise, the comment may be interpreted as a user or + group ID. + + When sudo is build with LDAP support the /etc/nsswitch.conf file is + now used to determine the sudoers seach order. sudo will default to + only using /etc/sudoers unless /etc/nsswitch.conf says otherwise. + This can be changed with an nsswitch.conf line, e.g.: + sudoers: ldap files + Would case LDAP to be searched first, then the sudoers file. + To restore the pre-1.7.0 behavior, run configure with the + --with-nsswitch=no flag. + + Sudo now ignores user .ldaprc files as well as system LDAP defaults. + All LDAP configuration is now in /etc/ldap.conf (or whichever file + was specified by configure's --with-ldap-conf-file option). + If you are using TLS, you may now need to specify: + tls_checkpeer no + in sudo's ldap.conf unless ldap.conf references a valid certificate + authority file(s). + + Please also see the WHATSNEW file for a list of new features in + sudo 1.7.0. + o Upgrading from a version prior to 1.6.9: Starting with sudo 1.6.9, if an OS supports a modular authentication diff --git a/WHATSNEW b/WHATSNEW new file mode 100644 index 0000000..2d36f06 --- /dev/null +++ b/WHATSNEW @@ -0,0 +1,79 @@ +What's new in Sudo 1.7.0? + + * Rewritten parser that converts sudoers into a set of data structures. + This eliminates a number of ordering issues and makes it possible to + apply sudoers Defaults entries before searching for the command. + It also adds support for per-command Defaults specifications. + + * Sudoers now supports a #include facility to allow the inclusion of other + sudoers-format files. + + * Sudo's -l (list) flag has been enhanced: + o applicable Defaults options are now listed + o a command argument can be specified for testing whether a user + may run a specific command. + o a new -U flag can be used in conjunction with "sudo -l" to allow + root (or a user with "sudo ALL") list another user's privileges. + + * A new -g flag has been added to allow the user to specify a + primary group to run the command as. The sudoers syntax has been + extended to include a group section in the Runas specification. + + * A uid may now be used anywhere a username is valid. + + * The "secure_path" run-time Defaults option has been restored. + + * Password and group data is now cached for fast lookups. + + * The file descriptor at which sudo starts closing all open files is now + configurable via sudoers and, optionally, the command line. + + * Visudo will now warn about aliases that are defined but not used. + + * The -i and -s command line flags now take an optional command + to be run via the shell. Previously, the argument was passed + to the shell as a script to run. + + * Improved LDAP support. SASL authentication may now be used in + conjunction when connecting to an LDAP server. The krb5_ccname + parameter in ldap.conf may be used to enable Kerberos. + + * Support for /etc/nsswitch.conf. LDAP users may now use nsswitch.conf + to specify the sudoers order. E.g.: + sudoers: ldap files + to check LDAP, then /etc/sudoers. The default is "files", even + when LDAP support is compiled in. This differs from sudo 1.6 + where LDAP was always consulted first. + + * Support for /etc/environment on AIX and Linux. If sudo is run + with the -i flag, the contents of /etc/environment are used to + populate the new environment that is passed to the command being + run. + + * If no terminal is available or if the new -A flag is specified, + sudo will use a helper program to read the password if one is + configured. Typically, this is a graphical password prompter + such as ssh-askpass. + + * A new Defaults option, "mailfrom" that sets the value of the + "From:" field in the warning/error mail. If unspecified, the + login name of the invoking user is used. + + * A new Defaults option, "env_file" that refers to a file containing + environment variables to be set in the command being run. + + * A new flag, -n, may be used to indicate that sudo should not + prompt the user for a password and, instead, exit with an error + if authentication is required. + + * If sudo needs to prompt for a password and it is unable to disable + echo (and no askpass program is defined), it will refuse to run + unless the "visiblepw" Defaults option has been specified. + + * Prior to version 1.7.0, hitting enter/return at the Password: prompt + would exit sudo. In sudo 1.7.0 and beyond, this is treated as + an empty password. To exit sudo, the user must press ^C or ^D + at the prompt. + + * visudo will now check the sudoers file owner and mode in -c (check) + mode when the -s (strict) flag is specified. diff --git a/aclocal.m4 b/aclocal.m4 index b751eeb..13089f0 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ dnl Local m4 macros for autoconf (used by sudo) dnl -dnl Copyright (c) 1994-1996,1998-2007 Todd C. Miller +dnl Copyright (c) 1994-1996,1998-2004 Todd C. Miller dnl dnl XXX - should cache values in all cases!!! dnl @@ -155,15 +155,6 @@ else fi ])dnl -dnl -dnl check for fullly working void -dnl -AC_DEFUN(SUDO_FULL_VOID, [AC_MSG_CHECKING(for full void implementation) -AC_TRY_COMPILE(, [void *foo; -foo = (void *)0; (void *)"test";], AC_DEFINE(VOID, void, [Define to "void" if your compiler supports void pointers, else use "char"].) -AC_MSG_RESULT(yes), AC_DEFINE(VOID, char) -AC_MSG_RESULT(no))]) - dnl dnl SUDO_CHECK_TYPE(TYPE, DEFAULT) dnl XXX - should require the check for unistd.h... @@ -234,6 +225,8 @@ AC_DEFUN([SUDO_FUNC_ISBLANK], ] [ if test "$sudo_cv_func_isblank" = "yes"; then AC_DEFINE(HAVE_ISBLANK, 1, [Define if you have isblank(3).]) + else + AC_LIBOBJ(isblank) fi ]) diff --git a/aix.c b/aix.c new file mode 100644 index 0000000..5897b6f --- /dev/null +++ b/aix.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2008 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 */ +#include + +#include + +#ifndef lint +__unused static const char rcsid[] = "$Sudo: aix.c,v 1.7 2008/11/06 00:42:37 millert Exp $"; +#endif /* lint */ + +#ifdef HAVE_GETUSERATTR + +#ifndef RLIM_SAVED_MAX +# define RLIM_SAVED_MAX RLIM_INFINITY +#endif + +struct aix_limit { + int resource; + char *soft; + char *hard; + int factor; +}; + +static struct aix_limit aix_limits[] = { + { RLIMIT_FSIZE, S_UFSIZE, S_UFSIZE_HARD, 512 }, + { RLIMIT_CPU, S_UCPU, S_UCPU_HARD, 1 }, + { RLIMIT_DATA, S_UDATA, S_UDATA_HARD, 512 }, + { RLIMIT_STACK, S_USTACK, S_USTACK_HARD, 512 }, + { RLIMIT_RSS, S_URSS, S_URSS_HARD, 512 }, + { RLIMIT_CORE, S_UCORE, S_UCORE_HARD, 512 }, + { RLIMIT_NOFILE, S_UNOFILE, S_UNOFILE_HARD, 1 } +}; + +static int +aix_getlimit(user, lim, valp) + char *user; + char *lim; + int *valp; +{ + if (getuserattr(user, lim, valp, SEC_INT) != 0) + return getuserattr("default", lim, valp, SEC_INT); + return(0); +} + +void +aix_setlimits(user) + char *user; +{ + struct rlimit rlim; + int i, n; + + /* + * For each resource limit, get the soft/hard values for the user + * and set those values via setrlimit(). Must be run as euid 0. + */ + for (n = 0; n < sizeof(aix_limits) / sizeof(aix_limits[0]); n++) { + /* + * We have two strategies, depending on whether or not the + * hard limit has been defined. + */ + if (aix_getlimit(user, aix_limits[n].hard, &i) == 0) { + rlim.rlim_max = i == -1 ? RLIM_INFINITY : i * aix_limits[n].factor; + if (aix_getlimit(user, aix_limits[n].soft, &i) == 0) + rlim.rlim_cur = i == -1 ? RLIM_INFINITY : i * aix_limits[n].factor; + else + rlim.rlim_cur = rlim.rlim_max; /* soft not specd, use hard */ + } else { + /* No hard limit set, try soft limit. */ + if (aix_getlimit(user, aix_limits[n].soft, &i) == 0) + rlim.rlim_cur = i == -1 ? RLIM_INFINITY : i * aix_limits[n].factor; + + /* Set hard limit per AIX /etc/security/limits documentation. */ + switch (aix_limits[n].resource) { + case RLIMIT_CPU: + case RLIMIT_FSIZE: + rlim.rlim_max = rlim.rlim_cur; + break; + case RLIMIT_STACK: + rlim.rlim_max = RLIM_SAVED_MAX; + break; + default: + rlim.rlim_max = RLIM_INFINITY; + break; + } + } + (void)setrlimit(aix_limits[n].resource, &rlim); + } +} + +#endif /* HAVE_GETUSERATTR */ diff --git a/alias.c b/alias.c new file mode 100644 index 0000000..9a03069 --- /dev/null +++ b/alias.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2004-2005m, 2007-2008 + * 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. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ + +#include "sudo.h" +#include "parse.h" +#include "redblack.h" +#include + +#ifndef lint +__unused static const char rcsid[] = "$Sudo: alias.c,v 1.14 2008/11/18 13:29:58 millert Exp $"; +#endif /* lint */ + +/* + * Globals + */ +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 +alias_compare(v1, v2) + const void *v1, *v2; +{ + const struct alias *a1 = (const struct alias *)v1; + const struct alias *a2 = (const struct alias *)v2; + int res; + + if (v1 == NULL) + res = -1; + else if (v2 == NULL) + res = 1; + else if ((res = strcmp(a1->name, a2->name)) == 0) + res = a1->type - a2->type; + return(res); +} + +/* + * Search the tree for an alias with the specified name and type. + * Returns a pointer to the alias structure or NULL if not found. + */ +struct alias * +find_alias(name, type) + char *name; + int type; +{ + struct alias key; + struct rbnode *node; + struct alias *a = NULL; + + key.name = name; + key.type = type; + if ((node = rbfind(aliases, &key)) != NULL) { + /* + * Compare the global sequence number with the one stored + * in the alias. If they match then we've seen this alias + * before and found a loop. + */ + a = node->data; + if (a->seqno == alias_seqno) + return(NULL); + a->seqno = alias_seqno; + } + return(a); +} + +/* + * Add an alias to the aliases redblack tree. + * Returns NULL on success and an error string on failure. + */ +char * +alias_add(name, type, members) + char *name; + int type; + struct member *members; +{ + static char errbuf[512]; + struct alias *a; + + a = emalloc(sizeof(*a)); + a->name = name; + a->type = type; + a->seqno = 0; + list2tq(&a->members, members); + if (rbinsert(aliases, a)) { + alias_free(a); + snprintf(errbuf, sizeof(errbuf), "Alias `%s' already defined", name); + return(errbuf); + } + return(NULL); +} + +/* + * Apply a function to each alias entry and pass in a cookie. + */ +void +alias_apply(func, cookie) + int (*func) __P((void *, void *)); + void *cookie; +{ + rbapply(aliases, func, cookie, inorder); +} + +/* + * Returns TRUE if there are no aliases, else FALSE. + */ +int +no_aliases() +{ + return(rbisempty(aliases)); +} + +/* + * Free memory used by an alias struct and its members. + */ +static void +alias_free(v) + void *v; +{ + struct alias *a = (struct alias *)v; + struct member *m; + struct sudo_command *c; + void *next; + + efree(a->name); + for (m = a->members.first; m != NULL; m = next) { + next = m->next; + if (m->type == COMMAND) { + c = (struct sudo_command *) m->name; + efree(c->cmnd); + efree(c->args); + } + efree(m->name); + efree(m); + } + efree(a); +} + +/* + * Find the named alias, delete it from the tree and recover its resources. + */ +int +alias_remove(name, type) + char *name; + int type; +{ + struct rbnode *node; + struct alias key, *a; + + key.name = name; + key.type = type; + if ((node = rbfind(aliases, &key)) == NULL) + return(FALSE); + a = rbdelete(aliases, node); + alias_free(a); + return(TRUE); +} + +void +init_aliases() +{ + if (aliases != NULL) + rbdestroy(aliases, alias_free); + aliases = rbcreate(alias_compare); +} diff --git a/alloc.c b/alloc.c index 745c8ae..c2405bf 100644 --- a/alloc.c +++ b/alloc.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2007 + * 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,11 +42,6 @@ #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) # include #endif /* HAVE_MALLOC_H && !STDC_HEADERS */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #ifdef HAVE_INTTYPES_H # include #endif @@ -53,7 +49,7 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: alloc.c,v 1.23.2.4 2007/09/11 12:20:15 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: alloc.c,v 1.33 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ /* @@ -74,17 +70,17 @@ __unused static const char rcsid[] = "$Sudo: alloc.c,v 1.23.2.4 2007/09/11 12:20 * emalloc() calls the system malloc(3) and exits with an error if * malloc(3) fails. */ -VOID * +void * emalloc(size) size_t size; { - VOID *ptr; + void *ptr; if (size == 0) - errx(1, "internal error, tried to emalloc(0)"); + errorx(1, "internal error, tried to emalloc(0)"); - if ((ptr = (VOID *) malloc(size)) == NULL) - errx(1, "unable to allocate memory"); + if ((ptr = malloc(size)) == NULL) + errorx(1, "unable to allocate memory"); return(ptr); } @@ -92,21 +88,21 @@ emalloc(size) * emalloc2() allocates nmemb * size bytes and exits with an error * if overflow would occur or if the system malloc(3) fails. */ -VOID * +void * emalloc2(nmemb, size) size_t nmemb; size_t size; { - VOID *ptr; + void *ptr; if (nmemb == 0 || size == 0) - errx(1, "internal error, tried to emalloc2(0)"); + errorx(1, "internal error, tried to emalloc2(0)"); if (nmemb > SIZE_MAX / size) - errx(1, "internal error, emalloc2() overflow"); + errorx(1, "internal error, emalloc2() overflow"); size *= nmemb; - if ((ptr = (VOID *) malloc(size)) == NULL) - errx(1, "unable to allocate memory"); + if ((ptr = malloc(size)) == NULL) + errorx(1, "unable to allocate memory"); return(ptr); } @@ -115,18 +111,18 @@ emalloc2(nmemb, size) * realloc(3) fails. You can call erealloc() with a NULL pointer even * if the system realloc(3) does not support this. */ -VOID * +void * erealloc(ptr, size) - VOID *ptr; + void *ptr; size_t size; { if (size == 0) - errx(1, "internal error, tried to erealloc(0)"); + errorx(1, "internal error, tried to erealloc(0)"); - ptr = ptr ? (VOID *) realloc(ptr, size) : (VOID *) malloc(size); + ptr = ptr ? realloc(ptr, size) : malloc(size); if (ptr == NULL) - errx(1, "unable to allocate memory"); + errorx(1, "unable to allocate memory"); return(ptr); } @@ -136,22 +132,22 @@ erealloc(ptr, size) * You can call erealloc() with a NULL pointer even if the system realloc(3) * does not support this. */ -VOID * +void * erealloc3(ptr, nmemb, size) - VOID *ptr; + void *ptr; size_t nmemb; size_t size; { if (nmemb == 0 || size == 0) - errx(1, "internal error, tried to erealloc3(0)"); + errorx(1, "internal error, tried to erealloc3(0)"); if (nmemb > SIZE_MAX / size) - errx(1, "internal error, erealloc3() overflow"); + errorx(1, "internal error, erealloc3() overflow"); size *= nmemb; - ptr = ptr ? (VOID *) realloc(ptr, size) : (VOID *) malloc(size); + ptr = ptr ? realloc(ptr, size) : malloc(size); if (ptr == NULL) - errx(1, "unable to allocate memory"); + errorx(1, "unable to allocate memory"); return(ptr); } @@ -199,7 +195,7 @@ easprintf(ret, fmt, va_alist) va_end(ap); if (len == -1) - errx(1, "unable to allocate memory"); + errorx(1, "unable to allocate memory"); return(len); } @@ -216,7 +212,7 @@ evasprintf(ret, format, args) int len; if ((len = vasprintf(ret, format, args)) == -1) - errx(1, "unable to allocate memory"); + errorx(1, "unable to allocate memory"); return(len); } @@ -225,7 +221,7 @@ evasprintf(ret, format, args) */ void efree(ptr) - VOID *ptr; + void *ptr; { if (ptr != NULL) free(ptr); diff --git a/alloca.c b/alloca.c deleted file mode 100644 index be98a41..0000000 --- a/alloca.c +++ /dev/null @@ -1,457 +0,0 @@ -/* alloca.c -- allocate automatically reclaimed memory - (Mostly) portable public-domain implementation -- D A Gwyn - - This implementation of the PWB library alloca function, - which is used to allocate space off the run-time stack so - that it is automatically reclaimed upon procedure exit, - was inspired by discussions with J. Q. Johnson of Cornell. - J.Otto Tennant contributed the Cray support. - - There are some preprocessor constants that can - be defined when compiling for your specific system, for - improved efficiency; however, the defaults should be okay. - - The general concept of this implementation is to keep - track of all alloca-allocated blocks, and reclaim any - that are found to be deeper in the stack than the current - invocation. This heuristic does not reclaim storage as - soon as it becomes invalid, but it will do so eventually. - - As a special case, alloca(0) reclaims storage without - allocating any. It is a good idea to use alloca(0) in - your main control loop, etc. to force garbage collection. */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -/* If compiling with GCC 2, this file's not needed. */ -#if !defined (__GNUC__) || __GNUC__ < 2 - -/* If someone has defined alloca as a macro, - there must be some other way alloca is supposed to work. */ -#ifndef alloca - -/* If your stack is a linked list of frames, you have to - provide an "address metric" ADDRESS_FUNCTION macro. */ - -#if defined (CRAY) && defined (CRAY_STACKSEG_END) -long i00afunc (); -#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) -#else -#define ADDRESS_FUNCTION(arg) &(arg) -#endif - -#if __STDC__ -typedef void *pointer; -#else -typedef char *pointer; -#endif - -#ifndef NULL -#define NULL 0 -#endif - -extern pointer malloc (); - -/* Define STACK_DIRECTION if you know the direction of stack - growth for your system; otherwise it will be automatically - deduced at run-time. - - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ - -#ifndef STACK_DIRECTION -#define STACK_DIRECTION 0 /* Direction unknown. */ -#endif - -#if STACK_DIRECTION != 0 - -#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ - -#else /* STACK_DIRECTION == 0; need run-time code. */ - -static int stack_dir; /* 1 or -1 once known. */ -#define STACK_DIR stack_dir - -static void -find_stack_direction () -{ - static char *addr = NULL; /* Address of first `dummy', once known. */ - auto char dummy; /* To get stack address. */ - - if (addr == NULL) - { /* Initial entry. */ - addr = ADDRESS_FUNCTION (dummy); - - find_stack_direction (); /* Recurse once. */ - } - else - { - /* Second entry. */ - if (ADDRESS_FUNCTION (dummy) > addr) - stack_dir = 1; /* Stack grew upward. */ - else - stack_dir = -1; /* Stack grew downward. */ - } -} - -#endif /* STACK_DIRECTION == 0 */ - -/* An "alloca header" is used to: - (a) chain together all alloca'ed blocks; - (b) keep track of stack depth. - - It is very important that sizeof(header) agree with malloc - alignment chunk size. The following default should work okay. */ - -#ifndef ALIGN_SIZE -#define ALIGN_SIZE sizeof(double) -#endif - -typedef union hdr -{ - char align[ALIGN_SIZE]; /* To force sizeof(header). */ - struct - { - union hdr *next; /* For chaining headers. */ - char *deep; /* For stack depth measure. */ - } h; -} header; - -static header *last_alloca_header = NULL; /* -> last alloca header. */ - -/* Return a pointer to at least SIZE bytes of storage, - which will be automatically reclaimed upon exit from - the procedure that called alloca. Originally, this space - was supposed to be taken from the current stack frame of the - caller, but that method cannot be made to work for some - implementations of C, for example under Gould's UTX/32. */ - -pointer -alloca (size) - unsigned size; -{ - auto char probe; /* Probes stack depth: */ - register char *depth = ADDRESS_FUNCTION (probe); - -#if STACK_DIRECTION == 0 - if (STACK_DIR == 0) /* Unknown growth direction. */ - find_stack_direction (); -#endif - - /* Reclaim garbage, defined as all alloca'd storage that - was allocated from deeper in the stack than currently. */ - - { - register header *hp; /* Traverses linked list. */ - - for (hp = last_alloca_header; hp != NULL;) - if ((STACK_DIR > 0 && hp->h.deep > depth) - || (STACK_DIR < 0 && hp->h.deep < depth)) - { - register header *np = hp->h.next; - - free ((pointer) hp); /* Collect garbage. */ - - hp = np; /* -> next header. */ - } - else - break; /* Rest are not deeper. */ - - last_alloca_header = hp; /* -> last valid storage. */ - } - - if (size == 0) - return NULL; /* No allocation required. */ - - /* Allocate combined header + user data storage. */ - - { - register pointer new = malloc (sizeof (header) + size); - /* Address of header. */ - - ((header *) new)->h.next = last_alloca_header; - ((header *) new)->h.deep = depth; - - last_alloca_header = (header *) new; - - /* User storage begins just after header. */ - - return (pointer) ((char *) new + sizeof (header)); - } -} - -#if defined (CRAY) && defined (CRAY_STACKSEG_END) - -#ifdef DEBUG_I00AFUNC -#include -#endif - -#ifndef CRAY_STACK -#define CRAY_STACK -#ifndef CRAY2 -/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ -struct stack_control_header - { - long shgrow:32; /* Number of times stack has grown. */ - long shaseg:32; /* Size of increments to stack. */ - long shhwm:32; /* High water mark of stack. */ - long shsize:32; /* Current size of stack (all segments). */ - }; - -/* The stack segment linkage control information occurs at - the high-address end of a stack segment. (The stack - grows from low addresses to high addresses.) The initial - part of the stack segment linkage control information is - 0200 (octal) words. This provides for register storage - for the routine which overflows the stack. */ - -struct stack_segment_linkage - { - long ss[0200]; /* 0200 overflow words. */ - long sssize:32; /* Number of words in this segment. */ - long ssbase:32; /* Offset to stack base. */ - long:32; - long sspseg:32; /* Offset to linkage control of previous - segment of stack. */ - long:32; - long sstcpt:32; /* Pointer to task common address block. */ - long sscsnm; /* Private control structure number for - microtasking. */ - long ssusr1; /* Reserved for user. */ - long ssusr2; /* Reserved for user. */ - long sstpid; /* Process ID for pid based multi-tasking. */ - long ssgvup; /* Pointer to multitasking thread giveup. */ - long sscray[7]; /* Reserved for Cray Research. */ - long ssa0; - long ssa1; - long ssa2; - long ssa3; - long ssa4; - long ssa5; - long ssa6; - long ssa7; - long sss0; - long sss1; - long sss2; - long sss3; - long sss4; - long sss5; - long sss6; - long sss7; - }; - -#else /* CRAY2 */ -/* The following structure defines the vector of words - returned by the STKSTAT library routine. */ -struct stk_stat - { - long now; /* Current total stack size. */ - long maxc; /* Amount of contiguous space which would - be required to satisfy the maximum - stack demand to date. */ - long high_water; /* Stack high-water mark. */ - long overflows; /* Number of stack overflow ($STKOFEN) calls. */ - long hits; /* Number of internal buffer hits. */ - long extends; /* Number of block extensions. */ - long stko_mallocs; /* Block allocations by $STKOFEN. */ - long underflows; /* Number of stack underflow calls ($STKRETN). */ - long stko_free; /* Number of deallocations by $STKRETN. */ - long stkm_free; /* Number of deallocations by $STKMRET. */ - long segments; /* Current number of stack segments. */ - long maxs; /* Maximum number of stack segments so far. */ - long pad_size; /* Stack pad size. */ - long current_address; /* Current stack segment address. */ - long current_size; /* Current stack segment size. This - number is actually corrupted by STKSTAT to - include the fifteen word trailer area. */ - long initial_address; /* Address of initial segment. */ - long initial_size; /* Size of initial segment. */ - }; - -/* The following structure describes the data structure which trails - any stack segment. I think that the description in 'asdef' is - out of date. I only describe the parts that I am sure about. */ - -struct stk_trailer - { - long this_address; /* Address of this block. */ - long this_size; /* Size of this block (does not include - this trailer). */ - long unknown2; - long unknown3; - long link; /* Address of trailer block of previous - segment. */ - long unknown5; - long unknown6; - long unknown7; - long unknown8; - long unknown9; - long unknown10; - long unknown11; - long unknown12; - long unknown13; - long unknown14; - }; - -#endif /* CRAY2 */ -#endif /* not CRAY_STACK */ - -#ifdef CRAY2 -/* Determine a "stack measure" for an arbitrary ADDRESS. - I doubt that "lint" will like this much. */ - -static long -i00afunc (address) - long *address; -{ - struct stk_stat status; - struct stk_trailer *trailer; - long *block, size; - long result = 0; - - /* We want to iterate through all of the segments. The first - step is to get the stack status structure. We could do this - more quickly and more directly, perhaps, by referencing the - $LM00 common block, but I know that this works. */ - - STKSTAT (&status); - - /* Set up the iteration. */ - - trailer = (struct stk_trailer *) (status.current_address - + status.current_size - - 15); - - /* There must be at least one stack segment. Therefore it is - a fatal error if "trailer" is null. */ - - if (trailer == 0) - abort (); - - /* Discard segments that do not contain our argument address. */ - - while (trailer != 0) - { - block = (long *) trailer->this_address; - size = trailer->this_size; - if (block == 0 || size == 0) - abort (); - trailer = (struct stk_trailer *) trailer->link; - if ((block <= address) && (address < (block + size))) - break; - } - - /* Set the result to the offset in this segment and add the sizes - of all predecessor segments. */ - - result = address - block; - - if (trailer == 0) - { - return result; - } - - do - { - if (trailer->this_size <= 0) - abort (); - result += trailer->this_size; - trailer = (struct stk_trailer *) trailer->link; - } - while (trailer != 0); - - /* We are done. Note that if you present a bogus address (one - not in any segment), you will get a different number back, formed - from subtracting the address of the first block. This is probably - not what you want. */ - - return (result); -} - -#else /* not CRAY2 */ -/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. - Determine the number of the cell within the stack, - given the address of the cell. The purpose of this - routine is to linearize, in some sense, stack addresses - for alloca. */ - -static long -i00afunc (address) - long address; -{ - long stkl = 0; - - long size, pseg, this_segment, stack; - long result = 0; - - struct stack_segment_linkage *ssptr; - - /* Register B67 contains the address of the end of the - current stack segment. If you (as a subprogram) store - your registers on the stack and find that you are past - the contents of B67, you have overflowed the segment. - - B67 also points to the stack segment linkage control - area, which is what we are really interested in. */ - - stkl = CRAY_STACKSEG_END (); - ssptr = (struct stack_segment_linkage *) stkl; - - /* If one subtracts 'size' from the end of the segment, - one has the address of the first word of the segment. - - If this is not the first segment, 'pseg' will be - nonzero. */ - - pseg = ssptr->sspseg; - size = ssptr->sssize; - - this_segment = stkl - size; - - /* It is possible that calling this routine itself caused - a stack overflow. Discard stack segments which do not - contain the target address. */ - - while (!(this_segment <= address && address <= stkl)) - { -#ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); -#endif - if (pseg == 0) - break; - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - this_segment = stkl - size; - } - - result = address - this_segment; - - /* If you subtract pseg from the current end of the stack, - you get the address of the previous stack segment's end. - This seems a little convoluted to me, but I'll bet you save - a cycle somewhere. */ - - while (pseg != 0) - { -#ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o\n", pseg, size); -#endif - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - result += size; - } - return (result); -} - -#endif /* not CRAY2 */ -#endif /* CRAY */ - -#endif /* no alloca */ -#endif /* not GCC version 2 */ diff --git a/auth/API b/auth/API index d586c64..fd183fe 100644 --- a/auth/API +++ b/auth/API @@ -10,7 +10,7 @@ typedef struct sudo_auth { short flags; /* various flags, see below */ short status; /* status from verify routine */ char *name; /* name of the method in string form */ - VOID *data; /* method-specific data pointer */ + void *data; /* method-specific data pointer */ int (*init) __P((struct passwd *pw, char **prompt, sudo_auth *auth)); int (*setup) __P((struct passwd *pw, char **prompt, sudo_auth *auth)); diff --git a/auth/afs.c b/auth/afs.c index 9118326..fed48ba 100644 --- a/auth/afs.c +++ b/auth/afs.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1999, 2001-2005 Todd C. Miller + * Copyright (c) 1999, 2001-2005, 2007 + * 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 @@ -46,12 +47,11 @@ #include "sudo.h" #include "sudo_auth.h" -#undef VOID #include #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: afs.c,v 1.10.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: afs.c,v 1.15 2008/11/09 14:13:13 millert Exp $"; #endif /* lint */ int diff --git a/auth/aix_auth.c b/auth/aix_auth.c index 168f358..14343ef 100644 --- a/auth/aix_auth.c +++ b/auth/aix_auth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2008 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.18.2.3 2007/06/21 22:29:15 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: aix_auth.c,v 1.25 2008/11/09 14:13:13 millert Exp $"; #endif /* lint */ /* @@ -75,3 +75,14 @@ aixauth_verify(pw, prompt, auth) } return(rval); } + +int +aixauth_cleanup(pw, auth) + struct passwd *pw; + sudo_auth *auth; +{ + /* Unset AUTHSTATE as it may not be correct for the runas user. */ + sudo_unsetenv("AUTHSTATE"); + + return(AUTH_SUCCESS); +} diff --git a/auth/bsdauth.c b/auth/bsdauth.c index a881bf9..aae7fd6 100644 --- a/auth/bsdauth.c +++ b/auth/bsdauth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Todd C. Miller + * Copyright (c) 2000-2005, 2007-2008 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_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: bsdauth.c,v 1.16.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: bsdauth.c,v 1.23 2008/11/09 14:13:13 millert Exp $"; #endif /* lint */ extern char *login_style; /* from sudo.c */ @@ -88,7 +88,7 @@ bsdauth_init(pw, promptp, auth) return(AUTH_FATAL); } - auth->data = (VOID *) as; + auth->data = (void *) as; return(AUTH_SUCCESS); } @@ -104,7 +104,6 @@ bsdauth_verify(pw, prompt, auth) int authok = 0; sigaction_t sa, osa; auth_session_t *as = (auth_session_t *) auth->data; - extern int nil_pw; /* save old signal handler */ sigemptyset(&sa.sa_mask); @@ -142,11 +141,8 @@ bsdauth_verify(pw, prompt, auth) } } - if (!pass || *pass == '\0') /* ^C or empty password */ - nil_pw = 1; - if (pass) { - authok = auth_userresponse(as, (char *)pass, 1); + authok = auth_userresponse(as, pass, 1); zero_bytes(pass, strlen(pass)); } @@ -156,6 +152,9 @@ bsdauth_verify(pw, prompt, auth) if (authok) return(AUTH_SUCCESS); + if (!pass) + return(AUTH_INTR); + if ((s = auth_getvalue(as, "errormsg")) != NULL) log_error(NO_EXIT|NO_MAIL, "%s", s); return(AUTH_FAILURE); diff --git a/auth/dce.c b/auth/dce.c index a27303b..f8ddcba 100644 --- a/auth/dce.c +++ b/auth/dce.c @@ -65,7 +65,7 @@ #include "sudo_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: dce.c,v 1.11.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: dce.c,v 1.14 2005/02/12 22:56:07 millert Exp $"; #endif /* lint */ static int check_dce_status __P((error_status_t, char *)); diff --git a/auth/fwtk.c b/auth/fwtk.c index 4e365fc..d09b132 100644 --- a/auth/fwtk.c +++ b/auth/fwtk.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2008 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,11 +41,6 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #include @@ -55,7 +50,7 @@ #include "sudo_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: fwtk.c,v 1.23.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: fwtk.c,v 1.29 2008/11/09 14:13:13 millert Exp $"; #endif /* lint */ int @@ -68,22 +63,22 @@ fwtk_init(pw, promptp, auth) char resp[128]; /* Response from the server */ if ((confp = cfg_read("sudo")) == (Cfg *)-1) { - warnx("cannot read fwtk config"); + warningx("cannot read fwtk config"); return(AUTH_FATAL); } if (auth_open(confp)) { - warnx("cannot connect to authentication server"); + warningx("cannot connect to authentication server"); return(AUTH_FATAL); } /* Get welcome message from auth server */ if (auth_recv(resp, sizeof(resp))) { - warnx("lost connection to authentication server"); + warningx("lost connection to authentication server"); return(AUTH_FATAL); } if (strncmp(resp, "Authsrv ready", 13) != 0) { - warnx("authentication server error:\n%s", resp); + warningx("authentication server error:\n%s", resp); return(AUTH_FATAL); } @@ -100,13 +95,12 @@ fwtk_verify(pw, prompt, auth) char buf[SUDO_PASS_MAX + 12]; /* General prupose buffer */ char resp[128]; /* Response from the server */ int error; - extern int nil_pw; /* Send username to authentication server. */ (void) snprintf(buf, sizeof(buf), "authorize %s 'sudo'", pw->pw_name); restart: if (auth_send(buf) || auth_recv(resp, sizeof(resp))) { - warnx("lost connection to authentication server"); + warningx("lost connection to authentication server"); return(AUTH_FATAL); } @@ -128,19 +122,17 @@ restart: strlcpy(buf, "response dummy", sizeof(buf)); goto restart; } else { - warnx("%s", resp); + warningx("%s", resp); return(AUTH_FATAL); } if (!pass) { /* ^C or error */ - nil_pw = 1; - return(AUTH_FAILURE); - } else if (*pass == '\0') /* empty password */ - nil_pw = 1; + return(AUTH_INTR); + } /* Send the user's response to the server */ (void) snprintf(buf, sizeof(buf), "response '%s'", pass); if (auth_send(buf) || auth_recv(resp, sizeof(resp))) { - warnx("lost connection to authentication server"); + warningx("lost connection to authentication server"); error = AUTH_FATAL; goto done; } @@ -152,7 +144,7 @@ restart: /* Main loop prints "Permission Denied" or insult. */ if (strcmp(resp, "Permission Denied.") != 0) - warnx("%s", resp); + warningx("%s", resp); error = AUTH_FAILURE; done: zero_bytes(pass, strlen(pass)); diff --git a/auth/kerb4.c b/auth/kerb4.c index 60d22ca..2f6c109 100644 --- a/auth/kerb4.c +++ b/auth/kerb4.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2007 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 @@ -48,7 +48,7 @@ #include "sudo_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: kerb4.c,v 1.11.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: kerb4.c,v 1.16 2008/11/09 14:13:13 millert Exp $"; #endif /* lint */ int @@ -68,7 +68,7 @@ kerb4_init(pw, promptp, auth) return(AUTH_FAILURE); /* Stash a pointer to the realm (used in kerb4_verify) */ - auth->data = (VOID *) realm; + auth->data = (void *) realm; return(AUTH_SUCCESS); } diff --git a/auth/kerb5.c b/auth/kerb5.c index 89d43a7..5e17685 100644 --- a/auth/kerb5.c +++ b/auth/kerb5.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2008 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 @@ #include "sudo_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: kerb5.c,v 1.23.2.8 2008/02/13 22:17:41 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: kerb5.c,v 1.36 2008/11/09 14:13:13 millert Exp $"; #endif /* lint */ #ifdef HAVE_HEIMDAL @@ -74,6 +74,24 @@ static struct _sudo_krb5_data { } sudo_krb5_data = { NULL, NULL, NULL }; typedef struct _sudo_krb5_data *sudo_krb5_datap; +#ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC +static krb5_error_code +krb5_get_init_creds_opt_alloc(context, opts) + krb5_context context; + krb5_get_init_creds_opt **opts; +{ + *opts = emalloc(sizeof(krb5_get_init_creds_opt)); + return 0; +} + +static void +krb5_get_init_creds_opt_free(opts) + krb5_get_init_creds_opt *opts; +{ + free(opts); +} +#endif + int kerb5_init(pw, promptp, auth) struct passwd *pw; @@ -87,7 +105,7 @@ kerb5_init(pw, promptp, auth) char cache_name[64]; char *pname; - auth->data = (VOID *) &sudo_krb5_data; /* Stash all our data here */ + auth->data = (void *) &sudo_krb5_data; /* Stash all our data here */ #ifdef HAVE_KRB5_INIT_SECURE_CONTEXT error = krb5_init_secure_context(&(sudo_krb5_data.sudo_context)); @@ -220,10 +238,10 @@ kerb5_verify(pw, pass, auth) done: if (opts) { -#ifdef HAVE_HEIMDAL - krb5_get_init_creds_opt_free(opts); -#else +#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_TWO_ARGS krb5_get_init_creds_opt_free(sudo_context, opts); +#else + krb5_get_init_creds_opt_free(opts); #endif } if (creds) diff --git a/auth/pam.c b/auth/pam.c index b2fe41a..cefb6d5 100644 --- a/auth/pam.c +++ b/auth/pam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2008 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 @@ -45,6 +45,7 @@ # include #endif /* HAVE_UNISTD_H */ #include +#include #ifdef HAVE_PAM_PAM_APPL_H # include @@ -72,12 +73,13 @@ #endif #ifndef lint -__unused static const char rcsid[] = "$Sudo: pam.c,v 1.43.2.10 2008/02/22 20:19:45 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: pam.c,v 1.66 2008/12/09 23:48:19 millert Exp $"; #endif /* lint */ static int sudo_conv __P((int, PAM_CONST struct pam_message **, - struct pam_response **, VOID *)); + struct pam_response **, void *)); static char *def_prompt; +static int gotintr; #ifndef PAM_DATA_SILENT #define PAM_DATA_SILENT 0 @@ -96,7 +98,7 @@ pam_init(pw, promptp, auth) /* Initial PAM setup */ if (auth != NULL) - auth->data = (VOID *) &pam_status; + auth->data = (void *) &pam_status; pam_conv.conv = sudo_conv; pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh); if (pam_status != PAM_SUCCESS) { @@ -162,6 +164,10 @@ pam_verify(pw, prompt, auth) } /* FALLTHROUGH */ case PAM_AUTH_ERR: + if (gotintr) { + /* error or ^C from tgetpass() */ + return(AUTH_INTR); + } case PAM_MAXTRIES: case PAM_PERM_DENIED: return(AUTH_FAILURE); @@ -244,17 +250,16 @@ sudo_conv(num_msg, msg, response, appdata_ptr) int num_msg; PAM_CONST struct pam_message **msg; struct pam_response **response; - VOID *appdata_ptr; + void *appdata_ptr; { struct pam_response *pr; PAM_CONST struct pam_message *pm; const char *prompt; char *pass; int n, flags, std_prompt; - extern int nil_pw; if ((*response = malloc(num_msg * sizeof(struct pam_response))) == NULL) - return(PAM_CONV_ERR); + return(PAM_SYSTEM_ERR); zero_bytes(*response, num_msg * sizeof(struct pam_response)); for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) { @@ -266,7 +271,7 @@ sudo_conv(num_msg, msg, response, appdata_ptr) prompt = def_prompt; /* Is the sudo prompt standard? (If so, we'l just use PAM's) */ - std_prompt = strncmp(def_prompt, "Password:", 9) == 0 && + std_prompt = strncmp(def_prompt, "Password:", 9) == 0 && (def_prompt[9] == '\0' || (def_prompt[9] == ' ' && def_prompt[10] == '\0')); @@ -282,18 +287,20 @@ sudo_conv(num_msg, msg, response, appdata_ptr) && (pm->msg[9] != ' ' || pm->msg[10] != '\0')))) prompt = pm->msg; #endif - /* Read the password. */ + /* Read the password unless interrupted. */ pass = tgetpass(prompt, def_passwd_timeout * 60, flags); if (pass == NULL) { /* We got ^C instead of a password; abort quickly. */ - nil_pw = 1; + if (errno == EINTR) + gotintr = 1; +#if defined(__darwin__) || defined(__APPLE__) + pass = ""; +#else goto err; +#endif } pr->resp = estrdup(pass); - if (*pr->resp == '\0') - nil_pw = 1; /* empty password */ - else - zero_bytes(pass, strlen(pass)); + zero_bytes(pass, strlen(pass)); break; case PAM_TEXT_INFO: if (pm->msg) @@ -324,5 +331,5 @@ err: zero_bytes(*response, num_msg * sizeof(struct pam_response)); free(*response); *response = NULL; - return(PAM_CONV_ERR); + return(gotintr ? PAM_AUTH_ERR : PAM_CONV_ERR); } diff --git a/auth/passwd.c b/auth/passwd.c index ffd12e3..7746a70 100644 --- a/auth/passwd.c +++ b/auth/passwd.c @@ -47,7 +47,7 @@ #include "sudo_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: passwd.c,v 1.14.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: passwd.c,v 1.17 2005/02/12 22:56:07 millert Exp $"; #endif /* lint */ #define DESLEN 13 diff --git a/auth/rfc1938.c b/auth/rfc1938.c index 079985b..8da824b 100644 --- a/auth/rfc1938.c +++ b/auth/rfc1938.c @@ -42,11 +42,6 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #if defined(HAVE_SKEY) @@ -69,7 +64,7 @@ #include "sudo_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: rfc1938.c,v 1.16.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: rfc1938.c,v 1.20 2005/02/12 22:56:07 millert Exp $"; #endif /* lint */ int @@ -113,7 +108,7 @@ rfc1938_setup(pw, promptp, auth) */ if (rfc1938challenge(&rfc1938, pw->pw_name, challenge, sizeof(challenge))) { if (IS_ONEANDONLY(auth)) { - warnx("you do not exist in the %s database", auth->name); + warningx("you do not exist in the %s database", auth->name); return(AUTH_FATAL); } else { return(AUTH_FAILURE); diff --git a/auth/secureware.c b/auth/secureware.c index 435957d..d398a60 100644 --- a/auth/secureware.c +++ b/auth/secureware.c @@ -54,7 +54,7 @@ #include "sudo_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: secureware.c,v 1.10.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: secureware.c,v 1.13 2005/02/12 22:56:07 millert Exp $"; #endif /* lint */ int diff --git a/auth/securid.c b/auth/securid.c index b16d44f..8ec7bbe 100644 --- a/auth/securid.c +++ b/auth/securid.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2007 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 @@ -44,11 +44,6 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #include @@ -59,7 +54,7 @@ #include "sudo_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: securid.c,v 1.12.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: securid.c,v 1.18 2008/11/09 14:13:13 millert Exp $"; #endif /* lint */ union config_record configure; @@ -72,7 +67,7 @@ securid_init(pw, promptp, auth) { static struct SD_CLIENT sd_dat; /* SecurID data block */ - auth->data = (VOID *) &sd_dat; /* For method-specific data */ + auth->data = (void *) &sd_dat; /* For method-specific data */ if (creadcfg() == 0) return(AUTH_SUCCESS); @@ -94,7 +89,7 @@ securid_setup(pw, promptp, auth) strlcpy(sd->username, pw->pw_name, 32); return(AUTH_SUCCESS); } else { - warnx("unable to contact the SecurID server"); + warningx("unable to contact the SecurID server"); return(AUTH_FATAL); } } diff --git a/auth/securid5.c b/auth/securid5.c index b6585c3..db254c2 100644 --- a/auth/securid5.c +++ b/auth/securid5.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2007 Todd C. Miller * Copyright (c) 2002 Michael Stroucken * * Permission to use, copy, modify, and distribute this software for any @@ -45,11 +45,6 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include /* Needed for SecurID v5.0 Authentication on UNIX */ @@ -61,7 +56,7 @@ #include "sudo_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: securid5.c,v 1.6.2.2 2007/06/12 00:56:44 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: securid5.c,v 1.13 2008/11/09 14:13:13 millert Exp $"; #endif /* lint */ /* @@ -84,13 +79,13 @@ securid_init(pw, promptp, auth) { static SDI_HANDLE sd_dat; /* SecurID handle */ - auth->data = (VOID *) &sd_dat; /* For method-specific data */ + auth->data = (void *) &sd_dat; /* For method-specific data */ /* Start communications */ if (AceInitialize() != SD_FALSE) return(AUTH_SUCCESS); - warnx("failed to initialise the ACE API library"); + warningx("failed to initialise the ACE API library"); return(AUTH_FATAL); } @@ -118,7 +113,7 @@ securid_setup(pw, promptp, auth) /* Re-initialize SecurID every time. */ if (SD_Init(sd) != ACM_OK) { - warnx("unable to contact the SecurID server"); + warningx("unable to contact the SecurID server"); return(AUTH_FATAL); } @@ -127,23 +122,23 @@ securid_setup(pw, promptp, auth) switch (retval) { case ACM_OK: - warnx("User ID locked for SecurID Authentication"); + warningx("User ID locked for SecurID Authentication"); return(AUTH_SUCCESS); case ACE_UNDEFINED_USERNAME: - warnx("invalid username length for SecurID"); + warningx("invalid username length for SecurID"); return(AUTH_FATAL); case ACE_ERR_INVALID_HANDLE: - warnx("invalid Authentication Handle for SecurID"); + warningx("invalid Authentication Handle for SecurID"); return(AUTH_FATAL); case ACM_ACCESS_DENIED: - warnx("SecurID communication failed"); + warningx("SecurID communication failed"); return(AUTH_FATAL); default: - warnx("unknown SecurID error"); + warningx("unknown SecurID error"); return(AUTH_FATAL); } } @@ -179,17 +174,17 @@ securid_verify(pw, pass, auth) break; case ACE_UNDEFINED_PASSCODE: - warnx("invalid passcode length for SecurID"); + warningx("invalid passcode length for SecurID"); rval = AUTH_FATAL; break; case ACE_UNDEFINED_USERNAME: - warnx("invalid username length for SecurID"); + warningx("invalid username length for SecurID"); rval = AUTH_FATAL; break; case ACE_ERR_INVALID_HANDLE: - warnx("invalid Authentication Handle for SecurID"); + warningx("invalid Authentication Handle for SecurID"); rval = AUTH_FATAL; break; @@ -228,7 +223,7 @@ then enter the new token code.\n", \ break; default: - warnx("unknown SecurID error"); + warningx("unknown SecurID error"); rval = AUTH_FATAL; break; } diff --git a/auth/sia.c b/auth/sia.c index d35a59d..852e8c7 100644 --- a/auth/sia.c +++ b/auth/sia.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2007 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 @@ -50,7 +50,7 @@ #include "sudo_auth.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: sia.c,v 1.14.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: sia.c,v 1.19 2008/11/09 14:13:13 millert Exp $"; #endif /* lint */ static int sudo_collect __P((int, int, uchar_t *, int, prompt_t *)); @@ -108,7 +108,7 @@ sia_setup(pw, promptp, auth) return(AUTH_FATAL); } - auth->data = (VOID *) siah; + auth->data = (void *) siah; return(AUTH_SUCCESS); } diff --git a/auth/sudo_auth.c b/auth/sudo_auth.c index a3cb56b..509f26f 100644 --- a/auth/sudo_auth.c +++ b/auth/sudo_auth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2008 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.33.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: sudo_auth.c,v 1.38 2008/11/07 17:45:52 millert Exp $"; #endif /* lint */ sudo_auth auth_switch[] = { @@ -88,8 +88,6 @@ sudo_auth auth_switch[] = { AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL) }; -int nil_pw; /* I hate resorting to globals like this... */ - void verify_user(pw, prompt) struct passwd *pw; @@ -156,14 +154,11 @@ verify_user(pw, prompt) } /* Get the password unless the auth function will do it for us */ - nil_pw = 0; #ifdef AUTH_STANDALONE p = prompt; #else p = (char *) tgetpass(prompt, def_passwd_timeout * 60, tgetpass_flags); - if (!p || *p == '\0') - nil_pw = 1; #endif /* AUTH_STANDALONE */ /* Call authentication functions. */ @@ -186,16 +181,8 @@ verify_user(pw, prompt) if (p) zero_bytes(p, strlen(p)); #endif - - /* Exit loop on nil password, but give it a chance to match first. */ - if (nil_pw) { - if (counter == def_passwd_tries) - exit(1); - else - break; - } - - pass_warn(stderr); + if (!ISSET(tgetpass_flags, TGP_ASKPASS)) + pass_warn(stderr); } cleanup: @@ -218,14 +205,18 @@ cleanup: case AUTH_SUCCESS: (void) sigaction(SIGTSTP, &osa, NULL); return; + case AUTH_INTR: case AUTH_FAILURE: - if (def_mail_badpass || def_mail_always) - flags = 0; - else - flags = NO_MAIL; - log_error(flags, "%d incorrect password attempt%s", - def_passwd_tries - counter, - (def_passwd_tries - counter == 1) ? "" : "s"); + if (counter != def_passwd_tries) { + if (def_mail_badpass || def_mail_always) + flags = 0; + else + flags = NO_MAIL; + log_error(flags, "%d incorrect password attempt%s", + def_passwd_tries - counter, + (def_passwd_tries - counter == 1) ? "" : "s"); + } + /* FALLTHROUGH */ case AUTH_FATAL: exit(1); } diff --git a/auth/sudo_auth.h b/auth/sudo_auth.h index f3b224e..ed1545f 100644 --- a/auth/sudo_auth.h +++ b/auth/sudo_auth.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2008 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.20.2.2 2007/06/12 01:28:42 millert Exp $ + * $Sudo: sudo_auth.h,v 1.28 2008/12/02 17:30:39 millert Exp $ */ #ifndef SUDO_AUTH_H @@ -22,13 +22,14 @@ /* Auth function return values. */ #define AUTH_SUCCESS 0 #define AUTH_FAILURE 1 -#define AUTH_FATAL 2 +#define AUTH_INTR 2 +#define AUTH_FATAL 3 typedef struct sudo_auth { short flags; /* various flags, see below */ short status; /* status from verify routine */ char *name; /* name of the method as a string */ - VOID *data; /* method-specific data pointer */ + void *data; /* method-specific data pointer */ int (*init) __P((struct passwd *pw, char **prompt, struct sudo_auth *auth)); int (*setup) __P((struct passwd *pw, char **prompt, struct sudo_auth *auth)); int (*verify) __P((struct passwd *pw, char *p, struct sudo_auth *auth)); @@ -57,6 +58,7 @@ int sia_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth)); int sia_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth)); int sia_cleanup __P((struct passwd *pw, sudo_auth *auth)); int aixauth_verify __P((struct passwd *pw, char *pass, sudo_auth *auth)); +int aixauth_cleanup __P((struct passwd *pw, sudo_auth *auth)); int bsdauth_init __P((struct passwd *pw, char **prompt, sudo_auth *auth)); int bsdauth_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth)); int bsdauth_cleanup __P((struct passwd *pw, sudo_auth *auth)); @@ -92,14 +94,14 @@ int securid_verify __P((struct passwd *pw, char *pass, sudo_auth *auth)); # define AUTH_STANDALONE \ AUTH_ENTRY(0, "SecurId", \ securid_init, securid_setup, securid_verify, NULL) -#elif defined(HAVE_SIA) +#elif defined(HAVE_SIA_SES_INIT) # define AUTH_STANDALONE \ AUTH_ENTRY(0, "sia", \ NULL, sia_setup, sia_verify, sia_cleanup) #elif defined(HAVE_AIXAUTH) # define AUTH_STANDALONE \ AUTH_ENTRY(0, "aixauth", \ - NULL, NULL, aixauth_verify, NULL) + NULL, NULL, aixauth_verify, aixauth_cleanup) #elif defined(HAVE_FWTK) # define AUTH_STANDALONE \ AUTH_ENTRY(0, "fwtk", \ diff --git a/check.c b/check.c index 4889ac7..fedc916 100644 --- a/check.c +++ b/check.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1993-1996,1998-2005 Todd C. Miller + * Copyright (c) 1993-1996,1998-2005, 2007-2008 + * 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 @@ -45,11 +46,6 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #include #include @@ -63,7 +59,7 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: check.c,v 1.223.2.10 2008/01/05 23:59:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: check.c,v 1.245 2008/11/25 17:01:34 millert Exp $"; #endif /* lint */ /* Status codes for timestamp_status() */ @@ -88,8 +84,9 @@ static void update_timestamp __P((char *, char *)); * verify who he/she is. */ void -check_user(validated) +check_user(validated, interactive) int validated; + int interactive; { char *timestampdir = NULL; char *timestampfile = NULL; @@ -103,7 +100,29 @@ check_user(validated) status = timestamp_status(timestampdir, timestampfile, user_name, TS_MAKE_DIRS); if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) { - lecture(status); + /* Bail out if we are non-interactive and a password is required */ + if (!interactive) + errorx(1, "sorry, a password is required to run %s", getprogname()); + + /* If user specified -A, make sure we have an askpass helper. */ + if (ISSET(tgetpass_flags, TGP_ASKPASS)) { + if (user_askpass == NULL) + log_error(NO_MAIL, + "no askpass program specified, try setting SUDO_ASKPASS"); + } else if (!ISSET(tgetpass_flags, TGP_STDIN)) { + /* If no tty but DISPLAY is set, use askpass if we have it. */ + if (!user_ttypath && !tty_present()) { + if (user_askpass && user_display && *user_display != '\0') { + SET(tgetpass_flags, TGP_ASKPASS); + } else if (!def_visiblepw) { + log_error(NO_MAIL, + "no tty present and no askpass program specified"); + } + } + } + + if (!ISSET(tgetpass_flags, TGP_ASKPASS)) + lecture(status); /* Expand any escapes in the prompt. */ prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt, @@ -211,7 +230,7 @@ expand_prompt(old_prompt, user, host) if (def_rootpw) len += 2; else if (def_targetpw || def_runaspw) - len += strlen(*user_runas) - 2; + len += strlen(runas_pw->pw_name) - 2; else len += strlen(user_name) - 2; subst = 1; @@ -223,7 +242,7 @@ expand_prompt(old_prompt, user, host) break; case 'U': p++; - len += strlen(*user_runas) - 2; + len += strlen(runas_pw->pw_name) - 2; subst = 1; break; case '%': @@ -262,7 +281,7 @@ expand_prompt(old_prompt, user, host) if (def_rootpw) n = strlcpy(np, "root", np - endp); else if (def_targetpw || def_runaspw) - n = strlcpy(np, *user_runas, np - endp); + n = strlcpy(np, runas_pw->pw_name, np - endp); else n = strlcpy(np, user_name, np - endp); if (n >= np - endp) @@ -278,7 +297,7 @@ expand_prompt(old_prompt, user, host) continue; case 'U': p++; - n = strlcpy(np, *user_runas, np - endp); + n = strlcpy(np, runas_pw->pw_name, np - endp); if (n >= np - endp) goto oflow; np += n; @@ -304,7 +323,7 @@ expand_prompt(old_prompt, user, host) oflow: /* We pre-allocate enough space, so this should never happen. */ - errx(1, "internal error, expand_prompt() overflow"); + errorx(1, "internal error, expand_prompt() overflow"); } /* @@ -319,7 +338,7 @@ user_is_exempt() if (!def_exempt_group) return(FALSE); - if (!(grp = getgrnam(def_exempt_group))) + if (!(grp = sudo_getgrnam(def_exempt_group))) return(FALSE); if (user_gid == grp->gr_gid) @@ -362,14 +381,14 @@ build_timestamp(timestampdir, timestampfile) p = user_tty; if (def_targetpw) len = easprintf(timestampfile, "%s/%s/%s:%s", dirparent, user_name, - p, *user_runas); + p, runas_pw->pw_name); else len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, p); if (len >= PATH_MAX) log_error(0, "timestamp path too long: %s", *timestampfile); } else if (def_targetpw) { len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, - *user_runas); + runas_pw->pw_name); if (len >= PATH_MAX) log_error(0, "timestamp path too long: %s", *timestampfile); } else @@ -584,7 +603,7 @@ remove_timestamp(remove) } else { timespecclear(&ts); if (touch(-1, path, &ts) == -1) - err(1, "can't reset %s to Epoch", path); + error(1, "can't reset %s to Epoch", path); } } diff --git a/closefrom.c b/closefrom.c index 2cdca65..0f043f4 100644 --- a/closefrom.c +++ b/closefrom.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2004-2005 Todd C. Miller + * Copyright (c) 2004-2005, 2007 + * 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 +50,7 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.6.2.3 2007/06/20 11:06:50 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.14 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ #ifndef HAVE_FCNTL_CLOSEM diff --git a/compat.h b/compat.h index 6469bb9..39fcdd7 100644 --- a/compat.h +++ b/compat.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 1996, 1998-2005 Todd C. Miller + * Copyright (c) 1996, 1998-2005, 2008 + * 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 @@ -17,7 +18,7 @@ * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. * - * $Sudo: compat.h,v 1.76.2.4 2007/06/12 01:28:41 millert Exp $ + * $Sudo: compat.h,v 1.90 2008/11/09 14:13:12 millert Exp $ */ #ifndef _SUDO_COMPAT_H @@ -40,11 +41,11 @@ #if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 5 # define __attribute__(x) #endif - + /* For silencing gcc warnings about rcsids */ #ifndef __unused # if defined(__GNUC__) && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ > 7) -# define __unused __attribute__((__unused__)) +# define __unused __attribute__((__unused__)) # else # define __unused # endif @@ -53,7 +54,7 @@ /* For catching format string mismatches */ #ifndef __printflike # if defined(__GNUC__) && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7) -# define __printflike(f, v) __attribute__((__format__ (__printf__, f, v))) +# define __printflike(f, v) __attribute__((__format__ (__printf__, f, v))) # else # define __printflike(f, v) # endif @@ -152,9 +153,10 @@ #endif /* - * Simple isblank() macro for systems without it. + * Simple isblank() macro and function for systems without it. */ #ifndef HAVE_ISBLANK +int isblank __P((int)); # define isblank(_x) ((_x) == ' ' || (_x) == '\t') #endif diff --git a/config.h.in b/config.h.in index a009a09..70de108 100644 --- a/config.h.in +++ b/config.h.in @@ -3,6 +3,10 @@ #ifndef _SUDO_CONFIG_H #define _SUDO_CONFIG_H +/* Define to `signed' or nothing if compiler does not support a signed + type qualifier. */ +#undef __signed + /* Define to 1 if the `syslog' function returns a non-zero int to denote failure. */ #undef BROKEN_SYSLOG @@ -60,12 +64,6 @@ /* Define to 1 if you have the `asprintf' function. */ #undef HAVE_ASPRINTF -/* Define to 1 if you have the `authenticate' function. */ -#undef HAVE_AUTHENTICATE - -/* Define to 1 if you have the `auth_challenge' function. */ -#undef HAVE_AUTH_CHALLENGE - /* Define to 1 if you have the `bigcrypt' function. */ #undef HAVE_BIGCRYPT @@ -94,9 +92,6 @@ /* Define to 1 if you have the `dispcrypt' function. */ #undef HAVE_DISPCRYPT -/* Define to 1 if you have the header file. */ -#undef HAVE_ERR_H - /* Define to 1 if your glob.h defines the GLOB_BRACE and GLOB_TILDE flags. */ #undef HAVE_EXTENDED_GLOB @@ -168,9 +163,18 @@ /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY +/* Define to 1 if you have the `getuserattr' function. */ +#undef HAVE_GETUSERATTR + /* Define to 1 if you have the `glob' function. */ #undef HAVE_GLOB +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_KRB5_H + +/* Define to 1 if you have the `gss_krb5_ccache_name' function. */ +#undef HAVE_GSS_KRB5_CCACHE_NAME + /* Define to 1 if your Kerberos is Heimdal. */ #undef HAVE_HEIMDAL @@ -206,6 +210,12 @@ /* Define to 1 if you use Kerberos V. */ #undef HAVE_KERB5 +/* Define to 1 if you have the `krb5_get_init_creds_opt_alloc' function. */ +#undef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC + +/* Define to 1 if your `krb5_get_init_creds_opt_alloc' function takes two arguments. */ +#undef HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_TWO_ARGS + /* Define to 1 if you have the `krb5_init_secure_context' function. */ #undef HAVE_KRB5_INIT_SECURE_CONTEXT @@ -218,15 +228,33 @@ /* Define to 1 if you use LDAP for sudoers. */ #undef HAVE_LDAP +/* Define to 1 if you have the `ldap_create' function. */ +#undef HAVE_LDAP_CREATE + /* Define to 1 if you have the `ldap_initialize' function. */ #undef HAVE_LDAP_INITIALIZE +/* Define to 1 if you have the `ldap_sasl_bind_s' function. */ +#undef HAVE_LDAP_SASL_BIND_S + +/* Define to 1 if you have the `ldap_sasl_interactive_bind_s' function. */ +#undef HAVE_LDAP_SASL_INTERACTIVE_BIND_S + +/* 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 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_str2dn' function. */ +#undef HAVE_LDAP_STR2DN + +/* Define to 1 if you have the `ldap_unbind_ext_s' function. */ +#undef HAVE_LDAP_UNBIND_EXT_S + /* Define to 1 if you have the `ldapssl_init' function. */ #undef HAVE_LDAPSSL_INIT @@ -245,9 +273,6 @@ /* Define to 1 if you have the `lrand48' function. */ #undef HAVE_LRAND48 -/* Define to 1 if you have the `lsearch' function. */ -#undef HAVE_LSEARCH - /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H @@ -296,15 +321,15 @@ /* Define to 1 if you have the `random' function. */ #undef HAVE_RANDOM +/* Define to 1 if you have the header file. */ +#undef HAVE_SASL_SASL_H + /* Define if your struct sockadr has an sa_len field. */ #undef HAVE_SA_LEN /* Define to 1 if you use SecurID for authentication. */ #undef HAVE_SECURID -/* Define to 1 if you have the header file. */ -#undef HAVE_SECURITY_PAM_APPL_H - /* Define to 1 to enable SELinux RBAC support. */ #undef HAVE_SELINUX @@ -329,9 +354,6 @@ /* Define to 1 if you have the `set_auth_parameters' function. */ #undef HAVE_SET_AUTH_PARAMETERS -/* Define to 1 if you use SIA authentication. */ -#undef HAVE_SIA - /* Define to 1 if you have the `sia_ses_init' function. */ #undef HAVE_SIA_SES_INIT @@ -341,9 +363,6 @@ /* Define to 1 if has the sigaction_t typedef. */ #undef HAVE_SIGACTION_T -/* Define to 1 if the system has the type `sig_atomic_t'. */ -#undef HAVE_SIG_ATOMIC_T - /* Define to 1 if you use S/Key. */ #undef HAVE_SKEY @@ -486,10 +505,6 @@ /* Define to 1 if you want a two line OTP (S/Key or OPIE) prompt. */ #undef LONG_OTP_PROMPT -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LT_OBJDIR - /* The subject of the mail sent by sudo to the MAILTO user/address. */ #undef MAILSUBJECT @@ -596,22 +611,9 @@ /* Define to 1 if you want a different ticket file for each tty. */ #undef USE_TTY_TICKETS -/* Define to "void" if your compiler supports void pointers, else use "char". - */ -#undef VOID - /* Define to avoid using the passwd/shadow file for authentication. */ #undef WITHOUT_PASSWD -/* Path to the ldap.conf file */ -#undef _PATH_LDAP_CONF - -/* Path to the ldap.secret file */ -#undef _PATH_LDAP_SECRET - -/* The fully qualified pathname of sudo_noexec.so */ -#undef _PATH_SUDO_NOEXEC - /* Define to empty if `const' does not conform to ANSI C. */ #undef const diff --git a/configure b/configure index c2fd192..0bf4e23 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for sudo 1.6.9. +# Generated by GNU Autoconf 2.61 for sudo 1.7. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. @@ -722,8 +722,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sudo' PACKAGE_TARNAME='sudo' -PACKAGE_VERSION='1.6.9' -PACKAGE_STRING='sudo 1.6.9' +PACKAGE_VERSION='1.7' +PACKAGE_STRING='sudo 1.7' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. @@ -822,6 +822,7 @@ SELINUX BAMAN LCMAN SEMAN +devdir mansectsu mansectform mansrcdir @@ -830,6 +831,10 @@ NOEXECDIR noexec_file INSTALL_NOEXEC DONT_LEAK_PATH_INFO +BSDAUTH_USAGE +SELINUX_USAGE +LDAP +LOGINCAP_USAGE timedir timeout password_timeout @@ -856,6 +861,9 @@ tty_tickets insults root_sudo path_info +ldap_conf +ldap_secret +nsswitch_conf EGREPPROG CC ac_ct_CC @@ -890,7 +898,6 @@ NROFFPROG YACC YFLAGS LIBOBJS -ALLOCA KRB5CONFIG LTLIBOBJS' ac_subst_files='' @@ -1407,7 +1414,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.6.9 to adapt to many kinds of systems. +\`configure' configures sudo 1.7 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1473,7 +1480,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sudo 1.6.9:";; + short | recursive ) echo "Configuration of sudo 1.7:";; esac cat <<\_ACEOF @@ -1490,8 +1497,10 @@ Optional Features: --enable-log-host Log the hostname in the log file --enable-noargs-shell If sudo is given no arguments run a shell --enable-shell-sets-home - set $HOME to target user in shell mode + Set $HOME to target user in shell mode --disable-path-info Print 'command not allowed' not 'command not found' + --enable-gss-krb5-ccache-name + Use GSS-API to set the Kerberos V cred cache name --enable-static[=PKGS] build static libraries [default=no] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-fast-install[=PKGS] @@ -1567,6 +1576,7 @@ 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-ldap-conf-file path to LDAP configuration file --with-ldap-secret-file path to LDAP secret password file @@ -1574,6 +1584,7 @@ Optional Packages: --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-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 @@ -1658,7 +1669,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sudo configure 1.6.9 +sudo configure 1.7 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1672,7 +1683,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.6.9, which was +It was created by sudo $as_me 1.7, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -2027,8 +2038,16 @@ 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.6.9" >&5 -echo "$as_me: Configuring Sudo version 1.6.9" >&6;} +{ echo "$as_me:$LINENO: Configuring Sudo version 1.7" >&5 +echo "$as_me: Configuring Sudo version 1.7" >&6;} + + + + + + + + @@ -2112,6 +2131,7 @@ insults=off root_sudo=on path_info=on INSTALL_NOEXEC= +devdir='$(srcdir)' PROGS="sudo visudo" : ${MANTYPE='man'} : ${mansrcdir='.'} @@ -2119,6 +2139,7 @@ PROGS="sudo visudo" : ${SUDOERS_UID='0'} : ${SUDOERS_GID='0'} DEV="#" +LDAP="#" SELINUX="#" BAMAN='.\" ' LCMAN='.\" ' @@ -2282,6 +2303,7 @@ echo "$as_me: Setting up for development: -Wall, flex, yacc" >&6;} PROGS="${PROGS} testsudoers" OSDEFS="${OSDEFS} -DSUDO_DEVEL" DEV="" + devdir=. ;; no) ;; *) { echo "$as_me:$LINENO: WARNING: Ignoring unknown argument to --with-devel: $with_devel" >&5 @@ -3547,6 +3569,27 @@ fi +# Check whether --with-nsswitch was given. +if test "${with_nsswitch+set}" = set; then + withval=$with_nsswitch; case $with_nsswitch in + no) ;; + yes) with_nsswitch="/etc/nsswitch.conf" + ;; + *) ;; +esac +fi + +if test ${with_nsswitch-"yes"} != "no"; then + cat >>confdefs.h <>confdefs.h <<_ACEOF -#define _PATH_LDAP_CONF "$with_ldap_conf_file" -_ACEOF - fi +cat >>confdefs.h <>confdefs.h <<_ACEOF -#define _PATH_LDAP_SECRET "$with_ldap_secret_file" -_ACEOF - fi +cat >>confdefs.h <&6; } fi +{ echo "$as_me:$LINENO: checking whether to use an askpass helper" >&5 +echo $ECHO_N "checking whether to use an askpass helper... $ECHO_C" >&6; } + +# Check whether --with-askpass was given. +if test "${with_askpass+set}" = set; then + withval=$with_askpass; case $with_askpass in + yes) { { echo "$as_me:$LINENO: error: \"--with-askpass takes a path as an argument.\"" >&5 +echo "$as_me: error: \"--with-askpass takes a path as an argument.\"" >&2;} + { (exit 1); exit 1; }; } + ;; + no) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _PATH_SUDO_ASKPASS "$with_askpass" +_ACEOF + + ;; +esac +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +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; } @@ -3947,7 +4018,8 @@ fi # Check whether --with-selinux was given. if test "${with_selinux+set}" = set; then withval=$with_selinux; case $with_selinux in - yes) cat >>confdefs.h <<\_ACEOF + yes) SELINUX_USAGE="[-r role] [-t type] " + cat >>confdefs.h <<\_ACEOF #define HAVE_SELINUX 1 _ACEOF @@ -3966,6 +4038,14 @@ esac fi +# Check whether --enable-gss_krb5_ccache_name was given. +if test "${enable_gss_krb5_ccache_name+set}" = set; then + enableval=$enable_gss_krb5_ccache_name; check_gss_krb5_ccache_name=$enableval +else + check_gss_krb5_ccache_name=no +fi + + # Extract the first word of "egrep", so it can be a program name with args. set dummy egrep; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 @@ -6129,7 +6209,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 6132 "configure"' > conftest.$ac_ext + echo '#line 6212 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -7988,11 +8068,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:7991: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8071: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7995: \$? = $ac_status" >&5 + echo "$as_me:8075: \$? = $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. @@ -8278,11 +8358,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:8281: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8361: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8285: \$? = $ac_status" >&5 + echo "$as_me:8365: \$? = $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. @@ -8382,11 +8462,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:8385: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8465: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8389: \$? = $ac_status" >&5 + echo "$as_me:8469: \$? = $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 @@ -10742,7 +10822,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 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 + + SUDO_OBJS="$SUDO_OBJS aix.o" ;; *-*-hiuxmpp*) : ${mansectsu='1m'} @@ -11881,6 +12058,10 @@ done : ${mansectsu='1m'} : ${mansectform='4'} + # HP-UX bundled compiler can't generate shared objects + if test "x$ac_cv_prog_cc_c89" = "xno"; then + with_noexec=no + fi case "$host" in *-*-hpux1-8.*) cat >>confdefs.h <<\_ACEOF @@ -13567,8 +13748,71 @@ fi done +if test "$OS" != "ultrix"; then + { echo "$as_me:$LINENO: checking POSIX termios" >&5 +echo $ECHO_N "checking POSIX termios... $ECHO_C" >&6; } +if test "${ac_cv_sys_posix_termios+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. */ +#include +#include +#include + +int +main () +{ +/* SunOS 4.0.3 has termios.h but not the library calls. */ + tcgetattr(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 + ac_cv_sys_posix_termios=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_sys_posix_termios=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: $ac_cv_sys_posix_termios" >&5 +echo "${ECHO_T}$ac_cv_sys_posix_termios" >&6; } + + if test "$ac_cv_sys_posix_termios" = "yes"; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_TERMIOS_H 1 +_ACEOF + + else -for ac_header in err.h +for ac_header in termio.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 @@ -13703,248 +13947,38 @@ if test `eval echo '${'$as_ac_Header'}'` = yes; then #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF -else - case " $LIBOBJS " in - *" err.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS err.$ac_objext" - ;; -esac - fi done -if test "$OS" != "ultrix"; then - { echo "$as_me:$LINENO: checking POSIX termios" >&5 -echo $ECHO_N "checking POSIX termios... $ECHO_C" >&6; } -if test "${ac_cv_sys_posix_termios+set}" = set; then + fi +fi +if test ${with_logincap-'no'} != "no"; then + +for ac_header in login_cap.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 + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } else - cat >conftest.$ac_ext <<_ACEOF + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $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 -#include - -int -main () -{ -/* SunOS 4.0.3 has termios.h but not the library calls. */ - tcgetattr(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 - ac_cv_sys_posix_termios=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_sys_posix_termios=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: $ac_cv_sys_posix_termios" >&5 -echo "${ECHO_T}$ac_cv_sys_posix_termios" >&6; } - - if test "$ac_cv_sys_posix_termios" = "yes"; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_TERMIOS_H 1 -_ACEOF - - else - -for ac_header in termio.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 - { echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -else - # Is the header compilable? -{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $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. */ -$ac_includes_default -#include <$ac_header> -_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 - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_compiler=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6; } - -# Is the header present? -{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $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 <$ac_header> -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -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_cpp conftest.$ac_ext") 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); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi - -rm -f conftest.err conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -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;} - - ;; -esac -{ echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - fi -fi -if test ${with_logincap-'no'} != "no"; then - -for ac_header in login_cap.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 - { echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -else - # Is the header compilable? -{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $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. */ -$ac_includes_default -#include <$ac_header> +$ac_includes_default +#include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" @@ -14055,7 +14089,7 @@ if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF - LCMAN="" + LOGINCAP_USAGE='[-c class|-] '; LCMAN="" case "$OS" in freebsd|netbsd) SUDO_LIBS="${SUDO_LIBS} -lutil" ;; @@ -14305,9 +14339,9 @@ _ACEOF fi -{ echo "$as_me:$LINENO: checking for sig_atomic_t" >&5 -echo $ECHO_N "checking for sig_atomic_t... $ECHO_C" >&6; } -if test "${ac_cv_type_sig_atomic_t+set}" = set; then +{ echo "$as_me:$LINENO: checking for __signed char" >&5 +echo $ECHO_N "checking for __signed char... $ECHO_C" >&6; } +if test "${ac_cv_type___signed_char+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF @@ -14316,10 +14350,8 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include -#include - -typedef sig_atomic_t ac__type_new_; +$ac_includes_default +typedef __signed char ac__type_new_; int main () { @@ -14348,35 +14380,24 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then - ac_cv_type_sig_atomic_t=yes + ac_cv_type___signed_char=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - ac_cv_type_sig_atomic_t=no + ac_cv_type___signed_char=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ echo "$as_me:$LINENO: result: $ac_cv_type_sig_atomic_t" >&5 -echo "${ECHO_T}$ac_cv_type_sig_atomic_t" >&6; } -if test $ac_cv_type_sig_atomic_t = yes; then - -cat >>confdefs.h <<_ACEOF -#define HAVE_SIG_ATOMIC_T 1 -_ACEOF - - +{ echo "$as_me:$LINENO: result: $ac_cv_type___signed_char" >&5 +echo "${ECHO_T}$ac_cv_type___signed_char" >&6; } +if test $ac_cv_type___signed_char = yes; then + : else - cat >>confdefs.h <<\_ACEOF -#define sig_atomic_t int -_ACEOF - -fi - -{ echo "$as_me:$LINENO: checking for sigaction_t" >&5 -echo $ECHO_N "checking for sigaction_t... $ECHO_C" >&6; } -if test "${ac_cv_type_sigaction_t+set}" = set; then + { echo "$as_me:$LINENO: checking for signed char" >&5 +echo $ECHO_N "checking for signed char... $ECHO_C" >&6; } +if test "${ac_cv_type_signed_char+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF @@ -14385,10 +14406,8 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include -#include - -typedef sigaction_t ac__type_new_; +$ac_includes_default +typedef signed char ac__type_new_; int main () { @@ -14417,33 +14436,166 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then - ac_cv_type_sigaction_t=yes + ac_cv_type_signed_char=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - ac_cv_type_sigaction_t=no + ac_cv_type_signed_char=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -{ echo "$as_me:$LINENO: result: $ac_cv_type_sigaction_t" >&5 -echo "${ECHO_T}$ac_cv_type_sigaction_t" >&6; } -if test $ac_cv_type_sigaction_t = yes; then - -cat >>confdefs.h <<_ACEOF -#define HAVE_SIGACTION_T 1 +{ echo "$as_me:$LINENO: result: $ac_cv_type_signed_char" >&5 +echo "${ECHO_T}$ac_cv_type_signed_char" >&6; } +if test $ac_cv_type_signed_char = yes; then + cat >>confdefs.h <<\_ACEOF +#define __signed signed _ACEOF -cat >>confdefs.h <<\_ACEOF -#define HAVE_SIGACTION_T 1 +else + cat >>confdefs.h <<\_ACEOF +#define __signed _ACEOF fi -{ echo "$as_me:$LINENO: checking for struct timespec" >&5 -echo $ECHO_N "checking for struct timespec... $ECHO_C" >&6; } -if test "${ac_cv_type_struct_timespec+set}" = set; then +fi + +{ echo "$as_me:$LINENO: checking for sig_atomic_t" >&5 +echo $ECHO_N "checking for sig_atomic_t... $ECHO_C" >&6; } +if test "${ac_cv_type_sig_atomic_t+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. */ +#include +#include + +typedef sig_atomic_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + 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 + ac_cv_type_sig_atomic_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_sig_atomic_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_sig_atomic_t" >&5 +echo "${ECHO_T}$ac_cv_type_sig_atomic_t" >&6; } +if test $ac_cv_type_sig_atomic_t = yes; then + : +else + cat >>confdefs.h <<\_ACEOF +#define sig_atomic_t int +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for sigaction_t" >&5 +echo $ECHO_N "checking for sigaction_t... $ECHO_C" >&6; } +if test "${ac_cv_type_sigaction_t+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. */ +#include +#include + +typedef sigaction_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + 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 + ac_cv_type_sigaction_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_sigaction_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_sigaction_t" >&5 +echo "${ECHO_T}$ac_cv_type_sigaction_t" >&6; } +if test $ac_cv_type_sigaction_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_SIGACTION_T 1 +_ACEOF + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SIGACTION_T 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for struct timespec" >&5 +echo $ECHO_N "checking for struct timespec... $ECHO_C" >&6; } +if test "${ac_cv_type_struct_timespec+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF @@ -14729,61 +14881,6 @@ _ACEOF fi -{ echo "$as_me:$LINENO: checking for full void implementation" >&5 -echo $ECHO_N "checking for full void implementation... $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. */ - -int -main () -{ -void *foo; -foo = (void *)0; (void *)"test"; - ; - 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 - -cat >>confdefs.h <<\_ACEOF -#define VOID void -_ACEOF - -{ echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - cat >>confdefs.h <<\_ACEOF -#define VOID char -_ACEOF - -{ echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: checking max length of uid_t" >&5 echo $ECHO_N "checking max length of uid_t... $ECHO_C" >&6; } @@ -16742,7 +16839,7 @@ fi done -for ac_func in lsearch +for ac_func in utimes do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 @@ -16832,20 +16929,37 @@ if test `eval echo '${'$as_ac_var'}'` = yes; then #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF -else - { echo "$as_me:$LINENO: checking for lsearch in -lcompat" >&5 -echo $ECHO_N "checking for lsearch in -lcompat... $ECHO_C" >&6; } -if test "${ac_cv_lib_compat_lsearch+set}" = set; then + +for ac_func in futimes futimesat +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 - ac_check_lib_save_LIBS=$LIBS -LIBS="-lcompat $LIBS" -cat >conftest.$ac_ext <<_ACEOF + 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 @@ -16853,11 +16967,18 @@ cat >>conftest.$ac_ext <<_ACEOF #ifdef __cplusplus extern "C" #endif -char lsearch (); +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 lsearch (); +return $ac_func (); ; return 0; } @@ -16880,282 +17001,36 @@ 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 - ac_cv_lib_compat_lsearch=yes + eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - ac_cv_lib_compat_lsearch=no + eval "$as_ac_var=no" fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS fi -{ echo "$as_me:$LINENO: result: $ac_cv_lib_compat_lsearch" >&5 -echo "${ECHO_T}$ac_cv_lib_compat_lsearch" >&6; } -if test $ac_cv_lib_compat_lsearch = yes; then - { echo "$as_me:$LINENO: checking for search.h" >&5 -echo $ECHO_N "checking for search.h... $ECHO_C" >&6; } -if test "${ac_cv_header_search_h+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. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -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_cpp conftest.$ac_ext") 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); } >/dev/null && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then - ac_cv_header_search_h=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_header_search_h=no -fi - -rm -f conftest.err conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_header_search_h" >&5 -echo "${ECHO_T}$ac_cv_header_search_h" >&6; } -if test $ac_cv_header_search_h = yes; then - cat >>confdefs.h <<\_ACEOF -#define HAVE_LSEARCH 1 -_ACEOF - LIBS="${LIBS} -lcompat" -else - case " $LIBOBJS " in - *" lsearch.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS lsearch.$ac_objext" - ;; -esac - -fi - - -else - case " $LIBOBJS " in - *" lsearch.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS lsearch.$ac_objext" - ;; -esac - -fi - -fi -done - - -for ac_func in utimes -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 - - -for ac_func in futimes futimesat -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 - break -fi -done - -else - -for ac_func in futime -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 +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 + break +fi +done + +else + +for ac_func in futime +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 @@ -17379,6 +17254,13 @@ cat >>confdefs.h <<\_ACEOF #define HAVE_ISBLANK 1 _ACEOF + else + case " $LIBOBJS " in + *" isblank.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS isblank.$ac_objext" + ;; +esac + fi @@ -19340,196 +19222,13 @@ fi fi -if test "$with_DCE" = "yes" -o "$ac_cv_prog_YACC" = "bison -y"; then - # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works -# for constant arguments. Useless! -{ echo "$as_me:$LINENO: checking for working alloca.h" >&5 -echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6; } -if test "${ac_cv_working_alloca_h+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. */ -#include -int -main () -{ -char *p = (char *) alloca (2 * sizeof (int)); - if (p) return 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 - ac_cv_working_alloca_h=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_working_alloca_h=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: $ac_cv_working_alloca_h" >&5 -echo "${ECHO_T}$ac_cv_working_alloca_h" >&6; } -if test $ac_cv_working_alloca_h = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_ALLOCA_H 1 -_ACEOF - -fi - -{ echo "$as_me:$LINENO: checking for alloca" >&5 -echo $ECHO_N "checking for alloca... $ECHO_C" >&6; } -if test "${ac_cv_func_alloca_works+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. */ -#ifdef __GNUC__ -# define alloca __builtin_alloca -#else -# ifdef _MSC_VER -# include -# define alloca _alloca -# else -# ifdef HAVE_ALLOCA_H -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca /* predefined by HP cc +Olibcalls */ -char *alloca (); -# endif -# endif -# endif -# endif -#endif - -int -main () -{ -char *p = (char *) alloca (1); - if (p) return 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 - ac_cv_func_alloca_works=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_func_alloca_works=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: $ac_cv_func_alloca_works" >&5 -echo "${ECHO_T}$ac_cv_func_alloca_works" >&6; } - -if test $ac_cv_func_alloca_works = yes; then - -cat >>confdefs.h <<\_ACEOF -#define HAVE_ALLOCA 1 -_ACEOF - -else - # The SVR3 libPW and SVR4 libucb both contain incompatible functions -# that cause trouble. Some versions do not even contain alloca or -# contain a buggy version. If you still want to use their alloca, -# use ar to extract alloca.o from them instead of compiling alloca.c. - -ALLOCA=\${LIBOBJDIR}alloca.$ac_objext - -cat >>confdefs.h <<\_ACEOF -#define C_ALLOCA 1 -_ACEOF - - -{ echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5 -echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6; } -if test "${ac_cv_os_cray+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. */ -#if defined CRAY && ! defined CRAY2 -webecray -#else -wenotbecray -#endif - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "webecray" >/dev/null 2>&1; then - ac_cv_os_cray=yes -else - ac_cv_os_cray=no -fi -rm -f conftest* - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5 -echo "${ECHO_T}$ac_cv_os_cray" >&6; } -if test $ac_cv_os_cray = yes; then - for ac_func in _getb67 GETB67 getb67; 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 + +for ac_func in getprogname +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 @@ -19610,147 +19309,115 @@ 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 CRAY_STACKSEG_END $ac_func + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF - break -fi - - done -fi +else -{ echo "$as_me:$LINENO: checking stack direction for C alloca" >&5 -echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6; } -if test "${ac_cv_c_stack_direction+set}" = set; then + { echo "$as_me:$LINENO: checking for __progname" >&5 +echo $ECHO_N "checking for __progname... $ECHO_C" >&6; } + if test "${sudo_cv___progname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - if test "$cross_compiling" = yes; then - ac_cv_c_stack_direction=0 -else - cat >conftest.$ac_ext <<_ACEOF + + 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 -find_stack_direction () -{ - static char *addr = 0; - auto char dummy; - if (addr == 0) - { - addr = &dummy; - return find_stack_direction (); - } - else - return (&dummy > addr) ? 1 : -1; -} int main () { - return find_stack_direction () < 0; +extern char *__progname; (void)puts(__progname); + ; + return 0; } _ACEOF -rm -f conftest$ac_exeext +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>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (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 + (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); }; }; then - ac_cv_c_stack_direction=1 + (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___progname=yes else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 + echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -( exit $ac_status ) -ac_cv_c_stack_direction=-1 -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext + sudo_cv___progname=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: $ac_cv_c_stack_direction" >&5 -echo "${ECHO_T}$ac_cv_c_stack_direction" >&6; } -cat >>confdefs.h <<_ACEOF -#define STACK_DIRECTION $ac_cv_c_stack_direction + if test "$sudo_cv___progname" = "yes"; then + cat >>confdefs.h <<\_ACEOF +#define HAVE___PROGNAME 1 _ACEOF + else + case " $LIBOBJS " in + *" getprogname.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS getprogname.$ac_objext" + ;; +esac + + fi + { echo "$as_me:$LINENO: result: $sudo_cv___progname" >&5 +echo "${ECHO_T}$sudo_cv___progname" >&6; } fi +done + + +if test -z "${AUTH_EXCL}${AUTH_REG}" -a -n "$AUTH_EXCL_DEF"; then + for auth in $AUTH_EXCL_DEF; do + case $auth in + AIX_AUTH) with_aixauth=maybe;; + BSD_AUTH) with_bsdauth=maybe;; + PAM) with_pam=maybe;; + SIA) CHECKSIA=true;; + esac + done fi -for ac_func in getprogname -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 +if test ${with_pam-"no"} != "no"; then + { echo "$as_me:$LINENO: checking for main in -ldl" >&5 +echo $ECHO_N "checking for main in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - cat >conftest.$ac_ext <<_ACEOF + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +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 main (); ; return 0; } @@ -19773,163 +19440,17 @@ 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" + ac_cv_lib_dl_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - eval "$as_ac_var=no" + ac_cv_lib_dl_main=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 - -else - - { echo "$as_me:$LINENO: checking for __progname" >&5 -echo $ECHO_N "checking for __progname... $ECHO_C" >&6; } - if test "${sudo_cv___progname+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 () -{ -extern char *__progname; (void)puts(__progname); - ; - 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___progname=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - sudo_cv___progname=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi - - if test "$sudo_cv___progname" = "yes"; then - cat >>confdefs.h <<\_ACEOF -#define HAVE___PROGNAME 1 -_ACEOF - - else - case " $LIBOBJS " in - *" getprogname.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS getprogname.$ac_objext" - ;; -esac - - fi - { echo "$as_me:$LINENO: result: $sudo_cv___progname" >&5 -echo "${ECHO_T}$sudo_cv___progname" >&6; } - -fi -done - - - -if test -z "${AUTH_EXCL}${AUTH_REG}" -a -n "$AUTH_EXCL_DEF"; then - for auth in $AUTH_EXCL_DEF; do - case $auth in - AIX_AUTH) with_aixauth=maybe;; - BSD_AUTH) with_bsdauth=maybe;; - PAM) with_pam=maybe;; - SIA) CHECKSIA=true;; - esac - done -fi - -if test ${with_pam-"no"} != "no"; then - { echo "$as_me:$LINENO: checking for main in -ldl" >&5 -echo $ECHO_N "checking for main in -ldl... $ECHO_C" >&6; } -if test "${ac_cv_lib_dl_main+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -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 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 - ac_cv_lib_dl_main=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_lib_dl_main=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS +LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_main" >&5 echo "${ECHO_T}$ac_cv_lib_dl_main" >&6; } @@ -20099,8 +19620,9 @@ echo "${ECHO_T}yes" >&6; } ;; no) { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } - cat >>confdefs.h <<\_ACEOF -#define NO_PAM_SESSION 1 + +cat >>confdefs.h <<\_ACEOF +#define NO_PAM_SESSION _ACEOF ;; @@ -20385,6 +19907,7 @@ if test $ac_cv_header_bsd_auth_h = yes; then _ACEOF AUTH_OBJS="$AUTH_OBJS bsdauth.o" + BSDAUTH_USAGE='[-a auth_type] ' AUTH_EXCL=BSD_AUTH; BAMAN="" else { { echo "$as_me:$LINENO: error: BSD authentication was specified but bsd_auth.h could not be found" >&5 @@ -21423,6 +20946,7 @@ echo "${ECHO_T}yes" >&6; } #define HAVE_HEIMDAL 1 _ACEOF + # XXX - need to check whether -lcrypo is needed! SUDO_LIBS="${SUDO_LIBS} -lkrb5 -lcrypto -ldes -lcom_err -lasn1" { echo "$as_me:$LINENO: checking for main in -lroken" >&5 echo $ECHO_N "checking for main in -lroken... $ECHO_C" >&6; } @@ -21560,7 +21084,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext LIBS="${LIBS} ${SUDO_LIBS}" -for ac_func in krb5_verify_user krb5_init_secure_context + +for ac_func in krb5_verify_user krb5_init_secure_context krb5_get_init_creds_opt_alloc do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 @@ -21653,6 +21178,69 @@ _ACEOF fi done + { echo "$as_me:$LINENO: checking whether krb5_get_init_creds_opt_free takes a two argument2" >&5 +echo $ECHO_N "checking whether krb5_get_init_creds_opt_free takes a two argument2... $ECHO_C" >&6; } +if test "${sudo_cv_krb5_get_init_creds_opt_free_two_args+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. */ +#include +int +main () +{ + + krb5_context context = NULL; + krb5_get_init_creds_opt *opts = NULL; + krb5_get_init_creds_opt_free(context, opts); + + ; + 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_krb5_get_init_creds_opt_free_two_args=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + sudo_cv_krb5_get_init_creds_opt_free_two_args=no + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + +fi +{ echo "$as_me:$LINENO: result: $sudo_cv_krb5_get_init_creds_opt_free_two_args" >&5 +echo "${ECHO_T}$sudo_cv_krb5_get_init_creds_opt_free_two_args" >&6; } + if test X"$sudo_cv_krb5_get_init_creds_opt_free_two_args" = X"yes"; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_TWO_ARGS 1 +_ACEOF + + fi LIBS="$_LIBS" fi @@ -22748,6 +22336,7 @@ if test ${with_ldap-'no'} != "no"; then CPPFLAGS="${CPPFLAGS} -I${with_ldap}/include" with_ldap=yes + LDAP="" fi SUDO_OBJS="${SUDO_OBJS} ldap.o" @@ -22945,133 +22534,690 @@ 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 - + + { 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 + +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 + + +for ac_header in sasl/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 + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $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. */ +$ac_includes_default +#include <$ac_header> +_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 + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $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 <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +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_cpp conftest.$ac_ext") 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); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +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;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in ldap_ssl.h mps/ldap_ssl.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; 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. */ +#include + +#include <$ac_header> +_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 + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + break +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; } +if test "${ac_cv_lib_gssapi_gss_krb5_ccache_name+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgssapi $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* 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 gss_krb5_ccache_name (); +int +main () +{ +return gss_krb5_ccache_name (); + ; + 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 + ac_cv_lib_gssapi_gss_krb5_ccache_name=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gssapi_gss_krb5_ccache_name=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gssapi_gss_krb5_ccache_name" >&5 +echo "${ECHO_T}$ac_cv_lib_gssapi_gss_krb5_ccache_name" >&6; } +if test $ac_cv_lib_gssapi_gss_krb5_ccache_name = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GSS_KRB5_CCACHE_NAME 1 +_ACEOF + + LDAP_LIBS="${LDAP_LIBS} -lgssapi" +else + { echo "$as_me:$LINENO: checking for gss_krb5_ccache_name in -lgssapi_krb5" >&5 +echo $ECHO_N "checking for gss_krb5_ccache_name in -lgssapi_krb5... $ECHO_C" >&6; } +if test "${ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgssapi_krb5 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* 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 gss_krb5_ccache_name (); +int +main () +{ +return gss_krb5_ccache_name (); + ; + 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 + ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name" >&5 +echo "${ECHO_T}$ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name" >&6; } +if test $ac_cv_lib_gssapi_krb5_gss_krb5_ccache_name = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_GSS_KRB5_CCACHE_NAME 1 +_ACEOF + + LDAP_LIBS="${LDAP_LIBS} -lgssapi_krb5" +fi + + +fi + + + # gssapi headers may be separate or part of Kerberos V + found=no + O_CPPFLAGS="$CPPFLAGS" + for dir in "" "kerberosV" "krb5" "kerberos5" "kerberosv5"; do + test X"$dir" != X"" && CPPFLAGS="$O_CPPFLAGS -I/usr/include/${dir}" + cat >conftest.$ac_ext <<_ACEOF +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +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_cpp conftest.$ac_ext") 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); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + found="gssapi/gssapi.h"; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + cat >conftest.$ac_ext <<_ACEOF +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +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_cpp conftest.$ac_ext") 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); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + found="gssapi.h"; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f conftest.err conftest.$ac_ext +fi + +rm -f conftest.err conftest.$ac_ext + done + if test X"$found" != X"no"; then + +for ac_header in $found +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 + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $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. */ +$ac_includes_default +#include <$ac_header> +_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 + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no fi -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext - - - - +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } -for ac_func in ldap_initialize ldap_start_tls_s ldapssl_init ldapssl_set_strength -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 +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $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. */ -/* 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; -} +#include <$ac_header> _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" +if { (ac_try="$ac_cpp conftest.$ac_ext" 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_cpp conftest.$ac_ext") 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" || + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$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" + }; then + ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - eval "$as_ac_var=no" + ac_header_preproc=no fi -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +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;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" fi -ac_res=`eval echo '${'$as_ac_var'}'` +ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_var'}'` = yes; then + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi -done +done + if test X"$found" = X"gssapi/gssapi.h"; then -for ac_header in ldap_ssl.h mps/ldap_ssl.h +for ac_header in gssapi/gssapi_krb5.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } else - cat >conftest.$ac_ext <<_ACEOF + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $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 - +$ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext @@ -23091,34 +23237,114 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then - eval "$as_ac_Header=yes" + ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - eval "$as_ac_Header=no" + ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $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 <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +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_cpp conftest.$ac_ext") 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); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +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;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } + +fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF - break + fi done + fi + else + CPPFLAGS="$O_CPPFLAGS" + { echo "$as_me:$LINENO: WARNING: Unable to locate gssapi.h, you will have to edit the Makefile and add -I/path/to/gssapi/includes to CPPFLAGS" >&5 +echo "$as_me: WARNING: Unable to locate gssapi.h, you will have to edit the Makefile and add -I/path/to/gssapi/includes to CPPFLAGS" >&2;} + fi + fi SUDO_LIBS="${SUDO_LIBS} ${LDAP_LIBS}" LIBS="$_LIBS" LDFLAGS="$_LDFLAGS" - # XXX - OpenLDAP has deprecated ldap_get_values() - CPPFLAGS="${CPPFLAGS} -DLDAP_DEPRECATED" fi if test -n "$blibpath"; then @@ -23267,7 +23493,7 @@ _ACEOF exec_prefix="$oexec_prefix" fi -ac_config_files="$ac_config_files Makefile sudo.man visudo.man sudoers.man" +ac_config_files="$ac_config_files Makefile sudo.man visudo.man sudoers.man sudoers.ldap.man sudo_usage.h" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -23665,7 +23891,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.6.9, which was +This file was extended by sudo $as_me 1.7, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -23714,7 +23940,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -sudo config.status 1.6.9 +sudo config.status 1.7 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" @@ -23827,6 +24053,8 @@ do "sudo.man") CONFIG_FILES="$CONFIG_FILES sudo.man" ;; "visudo.man") CONFIG_FILES="$CONFIG_FILES visudo.man" ;; "sudoers.man") CONFIG_FILES="$CONFIG_FILES sudoers.man" ;; + "sudoers.ldap.man") CONFIG_FILES="$CONFIG_FILES sudoers.ldap.man" ;; + "sudo_usage.h") CONFIG_FILES="$CONFIG_FILES sudo_usage.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} @@ -23948,6 +24176,7 @@ SELINUX!$SELINUX$ac_delim BAMAN!$BAMAN$ac_delim LCMAN!$LCMAN$ac_delim SEMAN!$SEMAN$ac_delim +devdir!$devdir$ac_delim mansectsu!$mansectsu$ac_delim mansectform!$mansectform$ac_delim mansrcdir!$mansrcdir$ac_delim @@ -23956,6 +24185,10 @@ NOEXECDIR!$NOEXECDIR$ac_delim noexec_file!$noexec_file$ac_delim INSTALL_NOEXEC!$INSTALL_NOEXEC$ac_delim DONT_LEAK_PATH_INFO!$DONT_LEAK_PATH_INFO$ac_delim +BSDAUTH_USAGE!$BSDAUTH_USAGE$ac_delim +SELINUX_USAGE!$SELINUX_USAGE$ac_delim +LDAP!$LDAP$ac_delim +LOGINCAP_USAGE!$LOGINCAP_USAGE$ac_delim timedir!$timedir$ac_delim timeout!$timeout$ac_delim password_timeout!$password_timeout$ac_delim @@ -23980,11 +24213,6 @@ env_editor!$env_editor$ac_delim passwd_tries!$passwd_tries$ac_delim tty_tickets!$tty_tickets$ac_delim insults!$insults$ac_delim -root_sudo!$root_sudo$ac_delim -path_info!$path_info$ac_delim -EGREPPROG!$EGREPPROG$ac_delim -CC!$CC$ac_delim -ac_ct_CC!$ac_ct_CC$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -24026,6 +24254,14 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +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 +EGREPPROG!$EGREPPROG$ac_delim +CC!$CC$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim EXEEXT!$EXEEXT$ac_delim OBJEXT!$OBJEXT$ac_delim CPP!$CPP$ac_delim @@ -24057,12 +24293,11 @@ NROFFPROG!$NROFFPROG$ac_delim YACC!$YACC$ac_delim YFLAGS!$YFLAGS$ac_delim LIBOBJS!$LIBOBJS$ac_delim -ALLOCA!$ALLOCA$ac_delim KRB5CONFIG!$KRB5CONFIG$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 34; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 41; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 @@ -24666,6 +24901,16 @@ fi + + + + + + + + + + diff --git a/configure.in b/configure.in index 109fc9a..6b09b5f 100644 --- a/configure.in +++ b/configure.in @@ -1,15 +1,15 @@ dnl dnl Process this file with GNU autoconf to produce a configure script. -dnl $Sudo: configure.in,v 1.413.2.53 2008/06/22 20:23:56 millert Exp $ +dnl $Sudo: configure.in,v 1.538 2008/12/09 21:13:01 millert Exp $ dnl -dnl Copyright (c) 1994-1996,1998-2007 Todd C. Miller +dnl Copyright (c) 1994-1996,1998-2008 Todd C. Miller dnl -AC_INIT([sudo], [1.6.9]) +AC_INIT([sudo], [1.7]) AC_CONFIG_HEADER(config.h pathnames.h) dnl dnl This won't work before AC_INIT dnl -AC_MSG_NOTICE([Configuring Sudo version 1.6.9]) +AC_MSG_NOTICE([Configuring Sudo version 1.7]) dnl dnl Variables that get substituted in the Makefile and man pages dnl @@ -37,6 +37,7 @@ AC_SUBST(SELINUX) AC_SUBST(BAMAN) AC_SUBST(LCMAN) AC_SUBST(SEMAN) +AC_SUBST(devdir) AC_SUBST(mansectsu) AC_SUBST(mansectform) AC_SUBST(mansrcdir) @@ -45,6 +46,10 @@ AC_SUBST(NOEXECDIR) AC_SUBST(noexec_file) AC_SUBST(INSTALL_NOEXEC) AC_SUBST(DONT_LEAK_PATH_INFO) +AC_SUBST(BSDAUTH_USAGE) +AC_SUBST(SELINUX_USAGE) +AC_SUBST(LDAP) +AC_SUBST(LOGINCAP_USAGE) dnl dnl Variables that get substituted in docs (not overridden by environment) dnl @@ -74,6 +79,9 @@ AC_SUBST(tty_tickets) AC_SUBST(insults) AC_SUBST(root_sudo) AC_SUBST(path_info) +AC_SUBST(ldap_conf) +AC_SUBST(ldap_secret) +AC_SUBST(nsswitch_conf) dnl dnl Initial values for above dnl @@ -103,6 +111,7 @@ insults=off root_sudo=on path_info=on INSTALL_NOEXEC= +devdir='$(srcdir)' dnl dnl Initial values for Makefile variables listed above dnl May be overridden by environment variables.. @@ -114,6 +123,7 @@ PROGS="sudo visudo" : ${SUDOERS_UID='0'} : ${SUDOERS_GID='0'} DEV="#" +LDAP="#" SELINUX="#" BAMAN='.\" ' LCMAN='.\" ' @@ -230,6 +240,7 @@ AC_ARG_WITH(devel, [ --with-devel add development options], PROGS="${PROGS} testsudoers" OSDEFS="${OSDEFS} -DSUDO_DEVEL" DEV="" + devdir=. ;; no) ;; *) AC_MSG_WARN([Ignoring unknown argument to --with-devel: $with_devel]) @@ -912,6 +923,20 @@ 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], +[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], [case $with_ldap in no) with_ldap="";; @@ -920,10 +945,14 @@ AC_ARG_WITH(ldap, [ --with-ldap[[=DIR]] enable LDAP support], AC_MSG_RESULT(yes) ;; esac]) -AC_ARG_WITH(ldap-conf-file, [ --with-ldap-conf-file path to LDAP configuration file], -[AC_DEFINE_UNQUOTED(_PATH_LDAP_CONF, "$with_ldap_conf_file", [Path to the ldap.conf file])]) -AC_ARG_WITH(ldap-secret-file, [ --with-ldap-secret-file path to LDAP secret password file], -[AC_DEFINE_UNQUOTED(_PATH_LDAP_SECRET, "$with_ldap_secret_file", [Path to the ldap.secret file])]) + +AC_ARG_WITH(ldap-conf-file, [ --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]) +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], [case $with_pc_insults in @@ -982,6 +1011,16 @@ 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], +[case $with_askpass in + yes) AC_MSG_ERROR(["--with-askpass takes a path as an argument."]) + ;; + no) ;; + *) AC_DEFINE_UNQUOTED(_PATH_SUDO_ASKPASS, "$with_askpass", [The fully qualified pathname of askpass]) + ;; +esac], AC_MSG_RESULT(no)) + dnl dnl Options for --enable dnl @@ -1098,7 +1137,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], + Set $HOME to target user in shell mode], [ case "$enableval" in yes) AC_MSG_RESULT(yes) AC_DEFINE(SHELL_SETS_HOME) @@ -1129,7 +1168,8 @@ AC_ARG_ENABLE(path_info, AC_ARG_WITH(selinux, [ --with-selinux enable SELinux support], [case $with_selinux in - yes) AC_DEFINE(HAVE_SELINUX) + yes) SELINUX_USAGE="[[-r role]] [[-t type]] " + AC_DEFINE(HAVE_SELINUX) SUDO_LIBS="${SUDO_LIBS} -lselinux" SUDO_OBJS="${SUDO_OBJS} selinux.o" PROGS="${PROGS} sesh" @@ -1141,6 +1181,12 @@ AC_ARG_WITH(selinux, [ --with-selinux enable SELinux support], ;; 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]) + dnl dnl If we don't have egrep we can't do anything... dnl @@ -1287,6 +1333,10 @@ case "$host" in if test X"$with_aixauth" = X""; then AC_CHECK_FUNCS(authenticate, [AUTH_EXCL_DEF="AIX_AUTH"]) fi + + # AIX-specific functions + AC_CHECK_FUNCS(getuserattr) + SUDO_OBJS="$SUDO_OBJS aix.o" ;; *-*-hiuxmpp*) : ${mansectsu='1m'} @@ -1300,6 +1350,10 @@ case "$host" in : ${mansectsu='1m'} : ${mansectform='4'} + # HP-UX bundled compiler can't generate shared objects + if test "x$ac_cv_prog_cc_c89" = "xno"; then + with_noexec=no + fi case "$host" in *-*-hpux[1-8].*) AC_DEFINE(BROKEN_SYSLOG) @@ -1650,7 +1704,6 @@ AC_HEADER_STDC AC_HEADER_DIRENT AC_HEADER_TIME AC_CHECK_HEADERS(malloc.h paths.h utime.h netgroup.h sys/sockio.h sys/bsdtypes.h sys/select.h) -AC_CHECK_HEADERS([err.h], [], [AC_LIBOBJ(err)]) dnl ultrix termio/termios are broken if test "$OS" != "ultrix"; then AC_SYS_POSIX_TERMIOS @@ -1661,7 +1714,7 @@ if test "$OS" != "ultrix"; then fi fi if test ${with_logincap-'no'} != "no"; then - AC_CHECK_HEADERS(login_cap.h, [LCMAN="" + AC_CHECK_HEADERS(login_cap.h, [LOGINCAP_USAGE='[[-c class|-]] '; LCMAN="" case "$OS" in freebsd|netbsd) SUDO_LIBS="${SUDO_LIBS} -lutil" ;; @@ -1677,7 +1730,8 @@ dnl typedef checks dnl AC_TYPE_MODE_T AC_TYPE_UID_T -AC_CHECK_TYPES([sig_atomic_t], , [AC_DEFINE(sig_atomic_t, int)], [#include +AC_CHECK_TYPE([__signed char], [], [AC_CHECK_TYPE([signed char], [AC_DEFINE(__signed, signed)], [AC_DEFINE(__signed, [])])]) +AC_CHECK_TYPE([sig_atomic_t], [], [AC_DEFINE(sig_atomic_t, int)], [#include #include ]) AC_CHECK_TYPES([sigaction_t], [AC_DEFINE(HAVE_SIGACTION_T)], [], [#include #include ]) @@ -1692,7 +1746,6 @@ SUDO_TYPE_SIZE_T SUDO_TYPE_SSIZE_T SUDO_TYPE_DEV_T SUDO_TYPE_INO_T -SUDO_FULL_VOID SUDO_UID_T_LEN SUDO_TYPE_LONG_LONG SUDO_SOCK_SA_LEN @@ -1732,7 +1785,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int i = GLOB_BRACE | AC_CHECK_FUNCS(lockf flock, [break]) AC_CHECK_FUNCS(waitpid wait3, [break]) AC_CHECK_FUNCS(innetgr _innetgr, [AC_CHECK_FUNCS(getdomainname) [break]]) -AC_CHECK_FUNCS(lsearch, [], [AC_CHECK_LIB([compat], [lsearch], [AC_CHECK_HEADER([search.h], [AC_DEFINE(HAVE_LSEARCH)] [LIBS="${LIBS} -lcompat"], [AC_LIBOBJ(lsearch)], -)], [AC_LIBOBJ(lsearch)])]) AC_CHECK_FUNCS(utimes, [AC_CHECK_FUNCS(futimes futimesat, [break])], [AC_CHECK_FUNCS(futime) AC_LIBOBJ(utimes)]) SUDO_FUNC_FNMATCH([AC_DEFINE(HAVE_FNMATCH)], [AC_LIBOBJ(fnmatch)]) SUDO_FUNC_ISBLANK @@ -1791,13 +1843,6 @@ dnl If syslog(3) not in libc, check -lsocket, -lnsl and -linet dnl AC_CHECK_FUNC(syslog, , [AC_CHECK_LIB(socket, syslog, [NET_LIBS="${NET_LIBS} -lsocket"; LIBS="${LIBS} -lsocket"], AC_CHECK_LIB(nsl, syslog, [NET_LIBS="${NET_LIBS} -lnsl"; LIBS="${LIBS} -lnsl"], AC_CHECK_LIB(inet, syslog, [NET_LIBS="${NET_LIBS} -linet"; LIBS="${LIBS} -linet"])))]) dnl -dnl Bison and DCE use alloca(3), if not in libc, use the sudo one (from gcc) -dnl (gcc includes its own alloca(3) but other compilers may not) -dnl -if test "$with_DCE" = "yes" -o "$ac_cv_prog_YACC" = "bison -y"; then - AC_FUNC_ALLOCA -fi -dnl dnl Check for getprogname() or __progname dnl AC_CHECK_FUNCS(getprogname, , [ @@ -1859,7 +1904,7 @@ if test ${with_pam-"no"} != "no"; then yes) AC_MSG_RESULT(yes) ;; no) AC_MSG_RESULT(no) - AC_DEFINE(NO_PAM_SESSION) + AC_DEFINE([NO_PAM_SESSION], [], [PAM session support disabled]) ;; *) AC_MSG_RESULT(no) AC_MSG_WARN([Ignoring unknown argument to --enable-pam-session: $enableval]) @@ -1901,6 +1946,7 @@ dnl if test ${with_bsdauth-'no'} != "no"; then AC_CHECK_HEADER(bsd_auth.h, AC_DEFINE(HAVE_BSD_AUTH_H) [AUTH_OBJS="$AUTH_OBJS bsdauth.o"] + [BSDAUTH_USAGE='[[-a auth_type]] '] [AUTH_EXCL=BSD_AUTH; BAMAN=""], [AC_MSG_ERROR([BSD authentication was specified but bsd_auth.h could not be found])]) fi @@ -2093,6 +2139,7 @@ if test ${with_kerb5-'no'} != "no" -a -z "$KRB5CONFIG"; then AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[const char *tmp = heimdal_version;]])], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_HEIMDAL) + # XXX - need to check whether -lcrypo is needed! SUDO_LIBS="${SUDO_LIBS} -lkrb5 -lcrypto -ldes -lcom_err -lasn1" AC_CHECK_LIB(roken, main, [SUDO_LIBS="${SUDO_LIBS} -lroken"]) ], [ @@ -2103,7 +2150,23 @@ if test ${with_kerb5-'no'} != "no" -a -z "$KRB5CONFIG"; then AUTH_OBJS="$AUTH_OBJS kerb5.o" _LIBS="$LIBS" LIBS="${LIBS} ${SUDO_LIBS}" - AC_CHECK_FUNCS(krb5_verify_user krb5_init_secure_context) + AC_CHECK_FUNCS(krb5_verify_user krb5_init_secure_context krb5_get_init_creds_opt_alloc) + AC_CACHE_CHECK(whether krb5_get_init_creds_opt_free takes a two argument2, + sudo_cv_krb5_get_init_creds_opt_free_two_args, [ + AC_TRY_COMPILE([#include ], + [ + krb5_context context = NULL; + krb5_get_init_creds_opt *opts = NULL; + krb5_get_init_creds_opt_free(context, opts); + ], + [sudo_cv_krb5_get_init_creds_opt_free_two_args=yes], + [sudo_cv_krb5_get_init_creds_opt_free_two_args=no] + ) + ] + ) + if test X"$sudo_cv_krb5_get_init_creds_opt_free_two_args" = X"yes"; then + AC_DEFINE(HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_TWO_ARGS) + fi LIBS="$_LIBS" fi @@ -2290,6 +2353,7 @@ if test ${with_ldap-'no'} != "no"; then SUDO_APPEND_LIBPATH(LDFLAGS, [${with_ldap}/lib]) CPPFLAGS="${CPPFLAGS} -I${with_ldap}/include" with_ldap=yes + LDAP="" fi SUDO_OBJS="${SUDO_OBJS} ldap.o" @@ -2325,14 +2389,40 @@ 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 ldapssl_init ldapssl_set_strength) + 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([ldap_ssl.h] [mps/ldap_ssl.h], [break], [], [#include ]) + if test X"$check_gss_krb5_ccache_name" = X"yes"; then + AC_CHECK_LIB(gssapi, gss_krb5_ccache_name, + AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME) + [LDAP_LIBS="${LDAP_LIBS} -lgssapi"], + AC_CHECK_LIB(gssapi_krb5, gss_krb5_ccache_name, + AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME) + [LDAP_LIBS="${LDAP_LIBS} -lgssapi_krb5"]) + ) + + # gssapi headers may be separate or part of Kerberos V + found=no + O_CPPFLAGS="$CPPFLAGS" + for dir in "" "kerberosV" "krb5" "kerberos5" "kerberosv5"; do + test X"$dir" != X"" && CPPFLAGS="$O_CPPFLAGS -I/usr/include/${dir}" + AC_PREPROC_IFELSE([#include ], [found="gssapi/gssapi.h"; break], [AC_PREPROC_IFELSE([#include ], [found="gssapi.h"; break])]) + done + if test X"$found" != X"no"; then + AC_CHECK_HEADERS([$found]) + if test X"$found" = X"gssapi/gssapi.h"; then + AC_CHECK_HEADERS([gssapi/gssapi_krb5.h]) + fi + else + CPPFLAGS="$O_CPPFLAGS" + AC_MSG_WARN([Unable to locate gssapi.h, you will have to edit the Makefile and add -I/path/to/gssapi/includes to CPPFLAGS]) + fi + fi + SUDO_LIBS="${SUDO_LIBS} ${LDAP_LIBS}" LIBS="$_LIBS" LDFLAGS="$_LDFLAGS" - # XXX - OpenLDAP has deprecated ldap_get_values() - CPPFLAGS="${CPPFLAGS} -DLDAP_DEPRECATED" fi dnl @@ -2392,8 +2482,7 @@ dnl test "$exec_prefix" = "NONE" && exec_prefix='$(prefix)' dnl -dnl Defer setting _PATH_SUDO_NOEXEC and _PATH_SUDO_SESH -dnl until after exec_prefix is set +dnl Defer setting _PATH_SUDO_NOEXEC until after exec_prefix is set dnl XXX - this is gross! dnl if test X"$with_noexec" != X"no" -o X"$with_selinux" != X"no"; then @@ -2422,7 +2511,7 @@ fi dnl dnl Substitute into the Makefile and man pages dnl -AC_CONFIG_FILES([Makefile sudo.man visudo.man sudoers.man]) +AC_CONFIG_FILES([Makefile sudo.man visudo.man sudoers.man sudoers.ldap.man sudo_usage.h]) AC_OUTPUT dnl @@ -2464,12 +2553,17 @@ AH_TEMPLATE(HAVE_GETPRPWNAM, [Define to 1 if you have the `getprpwnam' function. AH_TEMPLATE(HAVE_GETPWANAM, [Define to 1 if you have the `getpwanam' function. (SunOS 4.x shadow passwords)]) AH_TEMPLATE(HAVE_GETSPNAM, [Define to 1 if you have the `getspnam' function (SVR4-style shadow passwords)]) AH_TEMPLATE(HAVE_GETSPWUID, [Define to 1 if you have the `getspwuid' function. (HP-UX <= 9.X shadow passwords)]) +AH_TEMPLATE(HAVE_GSS_KRB5_CCACHE_NAME, [Define to 1 if you have the `gss_krb5_ccache_name' function.]) AH_TEMPLATE(HAVE_HEIMDAL, [Define to 1 if your Kerberos is Heimdal.]) AH_TEMPLATE(HAVE_IN6_ADDR, [Define to 1 if contains struct in6_addr.]) AH_TEMPLATE(HAVE_ISCOMSEC, [Define to 1 if you have the `iscomsec' function. (HP-UX >= 10.x check for shadow enabled)]) AH_TEMPLATE(HAVE_ISSECURE, [Define to 1 if you have the `issecure' function. (SunOS 4.x check for shadow enabled)]) AH_TEMPLATE(HAVE_KERB4, [Define to 1 if you use Kerberos IV.]) AH_TEMPLATE(HAVE_KERB5, [Define to 1 if you use Kerberos V.]) +AH_TEMPLATE(HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC, [Define to 1 if you have the `krb5_get_init_creds_opt_alloc' function.]) +AH_TEMPLATE(HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_TWO_ARGS, [Define to 1 if your `krb5_get_init_creds_opt_alloc' function takes two arguments.]) +AH_TEMPLATE(HAVE_KRB5_INIT_SECURE_CONTEXT, [Define to 1 if you have the `krb5_init_secure_context' function.]) +AH_TEMPLATE(HAVE_KRB5_VERIFY_USER, [Define to 1 if you have the `krb5_verify_user' function.]) AH_TEMPLATE(HAVE_LBER_H, [Define to 1 if your LDAP needs . (OpenLDAP does not)]) AH_TEMPLATE(HAVE_LDAP, [Define to 1 if you use LDAP for sudoers.]) AH_TEMPLATE(HAVE_OPIE, [Define to 1 if you use NRL OPIE.]) @@ -2477,7 +2571,6 @@ AH_TEMPLATE(HAVE_PAM, [Define to 1 if you use PAM authentication.]) AH_TEMPLATE(HAVE_PROJECT_H, [Define to 1 if you have the header file.]) AH_TEMPLATE(HAVE_SECURID, [Define to 1 if you use SecurID for authentication.]) AH_TEMPLATE(HAVE_SELINUX, [Define to 1 to enable SELinux RBAC support.]) -AH_TEMPLATE(HAVE_SIA, [Define to 1 if you use SIA authentication.]) AH_TEMPLATE(HAVE_SIGACTION_T, [Define to 1 if has the sigaction_t typedef.]) AH_TEMPLATE(HAVE_SKEY, [Define to 1 if you use S/Key.]) AH_TEMPLATE(HAVE_SKEYACCESS, [Define to 1 if your S/Key library has skeyaccess().]) @@ -2509,6 +2602,7 @@ AH_TEMPLATE(USE_STOW, [Define to 1 if you use GNU stow packaging.]) AH_TEMPLATE(USE_TTY_TICKETS, [Define to 1 if you want a different ticket file for each tty.]) 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.]) dnl dnl Bits to copy verbatim into config.h.in diff --git a/def_data.c b/def_data.c index ff9ebc6..72c14c9 100644 --- a/def_data.c +++ b/def_data.c @@ -186,6 +186,10 @@ struct sudo_defs_types sudo_defs_table[] = { "mailto", T_STR|T_BOOL, "Address to send mail to: %s", NULL, + }, { + "mailfrom", T_STR|T_BOOL, + "Address to send mail from: %s", + NULL, }, { "mailsub", T_STR, "Subject line for mail messages: %s", @@ -218,7 +222,10 @@ struct sudo_defs_types sudo_defs_table[] = { "runas_default", T_STR, "Default user to run commands as: %s", NULL, - set_runaspw, + }, { + "secure_path", T_STR|T_BOOL, + "Value to override user's $PATH with: %s", + NULL, }, { "editor", T_STR|T_PATH, "Path to the editor for use by visudo: %s", @@ -243,6 +250,14 @@ struct sudo_defs_types sudo_defs_table[] = { "ignore_local_sudoers", T_FLAG, "If LDAP directory is up, do we ignore local sudoers file", NULL, + }, { + "closefrom", T_INT, + "File descriptors >= %d will be closed before executing a command", + NULL, + }, { + "closefrom_override", T_FLAG, + "If set, users may override the value of `closefrom' with the -C option", + NULL, }, { "setenv", T_FLAG, "Allow users to set arbitrary environment variables", @@ -271,6 +286,22 @@ struct sudo_defs_types sudo_defs_table[] = { "type", T_STR, "SELinux type to use in the new security context: %s", NULL, + }, { + "askpass", T_STR|T_PATH|T_BOOL, + "Path to the askpass helper program: %s", + NULL, + }, { + "env_file", T_STR|T_PATH|T_BOOL, + "Path to the sudo-specific environment file: %s", + NULL, + }, { + "sudoers_locale", T_STR, + "Locale to use while parsing sudoers: %s", + NULL, + }, { + "visiblepw", T_FLAG, + "Allow sudo to prompt for a password even if it would be visisble", + NULL, }, { NULL, 0, NULL } diff --git a/def_data.h b/def_data.h index bbbd2ab..afa78e0 100644 --- a/def_data.h +++ b/def_data.h @@ -80,48 +80,64 @@ #define I_MAILERFLAGS 39 #define def_mailto (sudo_defs_table[40].sd_un.str) #define I_MAILTO 40 -#define def_mailsub (sudo_defs_table[41].sd_un.str) -#define I_MAILSUB 41 -#define def_badpass_message (sudo_defs_table[42].sd_un.str) -#define I_BADPASS_MESSAGE 42 -#define def_timestampdir (sudo_defs_table[43].sd_un.str) -#define I_TIMESTAMPDIR 43 -#define def_timestampowner (sudo_defs_table[44].sd_un.str) -#define I_TIMESTAMPOWNER 44 -#define def_exempt_group (sudo_defs_table[45].sd_un.str) -#define I_EXEMPT_GROUP 45 -#define def_passprompt (sudo_defs_table[46].sd_un.str) -#define I_PASSPROMPT 46 -#define def_passprompt_override (sudo_defs_table[47].sd_un.flag) -#define I_PASSPROMPT_OVERRIDE 47 -#define def_runas_default (sudo_defs_table[48].sd_un.str) -#define I_RUNAS_DEFAULT 48 -#define def_editor (sudo_defs_table[49].sd_un.str) -#define I_EDITOR 49 -#define def_listpw (sudo_defs_table[50].sd_un.tuple) -#define I_LISTPW 50 -#define def_verifypw (sudo_defs_table[51].sd_un.tuple) -#define I_VERIFYPW 51 -#define def_noexec (sudo_defs_table[52].sd_un.flag) -#define I_NOEXEC 52 -#define def_noexec_file (sudo_defs_table[53].sd_un.str) -#define I_NOEXEC_FILE 53 -#define def_ignore_local_sudoers (sudo_defs_table[54].sd_un.flag) -#define I_IGNORE_LOCAL_SUDOERS 54 -#define def_setenv (sudo_defs_table[55].sd_un.flag) -#define I_SETENV 55 -#define def_env_reset (sudo_defs_table[56].sd_un.flag) -#define I_ENV_RESET 56 -#define def_env_check (sudo_defs_table[57].sd_un.list) -#define I_ENV_CHECK 57 -#define def_env_delete (sudo_defs_table[58].sd_un.list) -#define I_ENV_DELETE 58 -#define def_env_keep (sudo_defs_table[59].sd_un.list) -#define I_ENV_KEEP 59 -#define def_role (sudo_defs_table[60].sd_un.str) -#define I_ROLE 60 -#define def_type (sudo_defs_table[61].sd_un.str) -#define I_TYPE 61 +#define def_mailfrom (sudo_defs_table[41].sd_un.str) +#define I_MAILFROM 41 +#define def_mailsub (sudo_defs_table[42].sd_un.str) +#define I_MAILSUB 42 +#define def_badpass_message (sudo_defs_table[43].sd_un.str) +#define I_BADPASS_MESSAGE 43 +#define def_timestampdir (sudo_defs_table[44].sd_un.str) +#define I_TIMESTAMPDIR 44 +#define def_timestampowner (sudo_defs_table[45].sd_un.str) +#define I_TIMESTAMPOWNER 45 +#define def_exempt_group (sudo_defs_table[46].sd_un.str) +#define I_EXEMPT_GROUP 46 +#define def_passprompt (sudo_defs_table[47].sd_un.str) +#define I_PASSPROMPT 47 +#define def_passprompt_override (sudo_defs_table[48].sd_un.flag) +#define I_PASSPROMPT_OVERRIDE 48 +#define def_runas_default (sudo_defs_table[49].sd_un.str) +#define I_RUNAS_DEFAULT 49 +#define def_secure_path (sudo_defs_table[50].sd_un.str) +#define I_SECURE_PATH 50 +#define def_editor (sudo_defs_table[51].sd_un.str) +#define I_EDITOR 51 +#define def_listpw (sudo_defs_table[52].sd_un.tuple) +#define I_LISTPW 52 +#define def_verifypw (sudo_defs_table[53].sd_un.tuple) +#define I_VERIFYPW 53 +#define def_noexec (sudo_defs_table[54].sd_un.flag) +#define I_NOEXEC 54 +#define def_noexec_file (sudo_defs_table[55].sd_un.str) +#define I_NOEXEC_FILE 55 +#define def_ignore_local_sudoers (sudo_defs_table[56].sd_un.flag) +#define I_IGNORE_LOCAL_SUDOERS 56 +#define def_closefrom (sudo_defs_table[57].sd_un.ival) +#define I_CLOSEFROM 57 +#define def_closefrom_override (sudo_defs_table[58].sd_un.flag) +#define I_CLOSEFROM_OVERRIDE 58 +#define def_setenv (sudo_defs_table[59].sd_un.flag) +#define I_SETENV 59 +#define def_env_reset (sudo_defs_table[60].sd_un.flag) +#define I_ENV_RESET 60 +#define def_env_check (sudo_defs_table[61].sd_un.list) +#define I_ENV_CHECK 61 +#define def_env_delete (sudo_defs_table[62].sd_un.list) +#define I_ENV_DELETE 62 +#define def_env_keep (sudo_defs_table[63].sd_un.list) +#define I_ENV_KEEP 63 +#define def_role (sudo_defs_table[64].sd_un.str) +#define I_ROLE 64 +#define def_type (sudo_defs_table[65].sd_un.str) +#define I_TYPE 65 +#define def_askpass (sudo_defs_table[66].sd_un.str) +#define I_ASKPASS 66 +#define def_env_file (sudo_defs_table[67].sd_un.str) +#define I_ENV_FILE 67 +#define def_sudoers_locale (sudo_defs_table[68].sd_un.str) +#define I_SUDOERS_LOCALE 68 +#define def_visiblepw (sudo_defs_table[69].sd_un.flag) +#define I_VISIBLEPW 69 enum def_tupple { never, diff --git a/def_data.in b/def_data.in index afc4e4c..0a0a3b8 100644 --- a/def_data.in +++ b/def_data.in @@ -6,6 +6,9 @@ # description (or NULL) # array of struct def_values if TYPE == T_TUPLE # +# NOTE: for tuples that can be used in a boolean context the first +# value corresponds to boolean FALSE and the second to TRUE. +# syslog T_LOGFAC|T_BOOL @@ -131,6 +134,9 @@ mailerflags mailto T_STR|T_BOOL "Address to send mail to: %s" +mailfrom + T_STR|T_BOOL + "Address to send mail from: %s" mailsub T_STR "Subject line for mail messages: %s" @@ -155,7 +161,9 @@ passprompt_override runas_default T_STR "Default user to run commands as: %s" - *set_runaspw +secure_path + T_STR|T_BOOL + "Value to override user's $PATH with: %s" editor T_STR|T_PATH "Path to the editor for use by visudo: %s" @@ -176,6 +184,12 @@ noexec_file ignore_local_sudoers T_FLAG "If LDAP directory is up, do we ignore local sudoers file" +closefrom + T_INT + "File descriptors >= %d will be closed before executing a command" +closefrom_override + T_FLAG + "If set, users may override the value of `closefrom' with the -C option" setenv T_FLAG "Allow users to set arbitrary environment variables" @@ -197,3 +211,15 @@ role type T_STR "SELinux type to use in the new security context: %s" +askpass + T_STR|T_PATH|T_BOOL + "Path to the askpass helper program: %s" +env_file + T_STR|T_PATH|T_BOOL + "Path to the sudo-specific environment file: %s" +sudoers_locale + T_STR + "Locale to use while parsing sudoers: %s" +visiblepw + T_FLAG + "Allow sudo to prompt for a password even if it would be visisble" diff --git a/defaults.c b/defaults.c index 7e7675e..376fef7 100644 --- a/defaults.c +++ b/defaults.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2008 + * 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 @@ -42,17 +43,14 @@ #include #endif /* HAVE_UNISTD_H */ #include -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #include "sudo.h" +#include "parse.h" +#include #ifndef lint -__unused static const char rcsid[] = "$Sudo: defaults.c,v 1.48.2.5 2007/06/18 15:51:35 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: defaults.c,v 1.73 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ /* @@ -95,8 +93,6 @@ static struct strmap priorities[] = { { NULL, -1 } }; -extern int sudolineno; - /* * Local prototypes. */ @@ -232,8 +228,7 @@ set_default(var, val, op) break; } if (!cur->name) { - warnx("unknown defaults entry `%s' referenced near line %d", - var, sudolineno); + warningx("unknown defaults entry `%s'", var); return(FALSE); } @@ -241,20 +236,18 @@ set_default(var, val, op) case T_LOGFAC: if (!store_syslogfac(val, cur, op)) { if (val) - warnx("value `%s' is invalid for option `%s'", val, var); + warningx("value `%s' is invalid for option `%s'", val, var); else - warnx("no value specified for `%s' on line %d", - var, sudolineno); + warningx("no value specified for `%s'", var); return(FALSE); } break; case T_LOGPRI: if (!store_syslogpri(val, cur, op)) { if (val) - warnx("value `%s' is invalid for option `%s'", val, var); + warningx("value `%s' is invalid for option `%s'", val, var); else - warnx("no value specified for `%s' on line %d", - var, sudolineno); + warningx("no value specified for `%s'", var); return(FALSE); } break; @@ -262,17 +255,16 @@ set_default(var, val, op) if (!val) { /* Check for bogus boolean usage or lack of a value. */ if (!ISSET(cur->type, T_BOOL) || op != FALSE) { - warnx("no value specified for `%s' on line %d", - var, sudolineno); + warningx("no value specified for `%s'", var); return(FALSE); } } if (ISSET(cur->type, T_PATH) && val && *val != '/') { - warnx("values for `%s' must start with a '/'", var); + warningx("values for `%s' must start with a '/'", var); return(FALSE); } if (!store_str(val, cur, op)) { - warnx("value `%s' is invalid for option `%s'", val, var); + warningx("value `%s' is invalid for option `%s'", val, var); return(FALSE); } break; @@ -280,13 +272,12 @@ set_default(var, val, op) if (!val) { /* Check for bogus boolean usage or lack of a value. */ if (!ISSET(cur->type, T_BOOL) || op != FALSE) { - warnx("no value specified for `%s' on line %d", - var, sudolineno); + warningx("no value specified for `%s'", var); return(FALSE); } } if (!store_int(val, cur, op)) { - warnx("value `%s' is invalid for option `%s'", val, var); + warningx("value `%s' is invalid for option `%s'", val, var); return(FALSE); } break; @@ -294,13 +285,12 @@ set_default(var, val, op) if (!val) { /* Check for bogus boolean usage or lack of a value. */ if (!ISSET(cur->type, T_BOOL) || op != FALSE) { - warnx("no value specified for `%s' on line %d", - var, sudolineno); + warningx("no value specified for `%s'", var); return(FALSE); } } if (!store_uint(val, cur, op)) { - warnx("value `%s' is invalid for option `%s'", val, var); + warningx("value `%s' is invalid for option `%s'", val, var); return(FALSE); } break; @@ -308,20 +298,18 @@ set_default(var, val, op) if (!val) { /* Check for bogus boolean usage or lack of a value. */ if (!ISSET(cur->type, T_BOOL) || op != FALSE) { - warnx("no value specified for `%s' on line %d", - var, sudolineno); + warningx("no value specified for `%s'", var); return(FALSE); } } if (!store_mode(val, cur, op)) { - warnx("value `%s' is invalid for option `%s'", val, var); + warningx("value `%s' is invalid for option `%s'", val, var); return(FALSE); } break; case T_FLAG: if (val) { - warnx("option `%s' does not take a value on line %d", - var, sudolineno); + warningx("option `%s' does not take a value", var); return(FALSE); } cur->sd_un.flag = op; @@ -334,24 +322,22 @@ set_default(var, val, op) if (!val) { /* Check for bogus boolean usage or lack of a value. */ if (!ISSET(cur->type, T_BOOL) || op != FALSE) { - warnx("no value specified for `%s' on line %d", - var, sudolineno); + warningx("no value specified for `%s'", var); return(FALSE); } } if (!store_list(val, cur, op)) { - warnx("value `%s' is invalid for option `%s'", val, var); + warningx("value `%s' is invalid for option `%s'", val, var); return(FALSE); } break; case T_TUPLE: if (!val && !ISSET(cur->type, T_BOOL)) { - warnx("no value specified for `%s' on line %d", - var, sudolineno); + warningx("no value specified for `%s'", var); return(FALSE); } if (!store_tuple(val, cur, op)) { - warnx("value `%s' is invalid for option `%s'", val, var); + warningx("value `%s' is invalid for option `%s'", val, var); return(FALSE); } break; @@ -370,9 +356,9 @@ init_defaults() static int firsttime = 1; struct sudo_defs_types *def; - /* Free any strings that were set. */ + /* Clear any old settings. */ if (!firsttime) { - for (def = sudo_defs_table; def->name; def++) + for (def = sudo_defs_table; def->name; def++) { switch (def->type & T_MASK) { case T_STR: efree(def->sd_un.str); @@ -382,6 +368,8 @@ init_defaults() list_op(NULL, 0, def, freeall); break; } + zero_bytes(&def->sd_un, sizeof(def->sd_un)); + } } /* First initialize the flags. */ @@ -436,8 +424,13 @@ init_defaults() #ifdef ENV_EDITOR def_env_editor = TRUE; #endif +#ifdef _PATH_SUDO_ASKPASS + def_askpass = estrdup(_PATH_SUDO_ASKPASS); +#endif + def_sudoers_locale = estrdup("C"); def_env_reset = TRUE; def_set_logname = TRUE; + def_closefrom = STDERR_FILENO + 1; /* Syslog options need special care since they both strings and ints */ #if (LOGGING & SLOG_SYSLOG) @@ -479,6 +472,9 @@ init_defaults() #endif #ifdef EXEMPTGROUP def_exempt_group = estrdup(EXEMPTGROUP); +#endif +#ifdef SECURE_PATH + def_secure_path = estrdup(SECURE_PATH); #endif def_editor = estrdup(EDITOR); #ifdef _PATH_SUDO_NOEXEC @@ -488,17 +484,55 @@ init_defaults() /* Finally do the lists (currently just environment tables). */ init_envtables(); - /* - * The following depend on the above values. - * We use a pointer to the string so that if its - * value changes we get the change. - */ - if (user_runas == NULL) - user_runas = &def_runas_default; - firsttime = 0; } +/* + * Update the defaults based on what was set by sudoers. + * Pass in a an OR'd list of which default types to update. + */ +int +update_defaults(what) + int what; +{ + struct defaults *def; + + tq_foreach_fwd(&defaults, def) { + switch (def->type) { + case DEFAULTS: + if (ISSET(what, SETDEF_GENERIC) && + !set_default(def->var, def->val, def->op)) + return(FALSE); + break; + case DEFAULTS_USER: + if (ISSET(what, SETDEF_USER) && + userlist_matches(sudo_user.pw, &def->binding) == ALLOW && + !set_default(def->var, def->val, def->op)) + return(FALSE); + break; + case DEFAULTS_RUNAS: + if (ISSET(what, SETDEF_RUNAS) && + runaslist_matches(&def->binding, NULL) == ALLOW && + !set_default(def->var, def->val, def->op)) + return(FALSE); + break; + case DEFAULTS_HOST: + if (ISSET(what, SETDEF_HOST) && + hostlist_matches(&def->binding) == ALLOW && + !set_default(def->var, def->val, def->op)) + return(FALSE); + break; + case DEFAULTS_CMND: + if (ISSET(what, SETDEF_CMND) && + cmndlist_matches(&def->binding) == ALLOW && + !set_default(def->var, def->val, def->op)) + return(FALSE); + break; + } + } + return(TRUE); +} + static int store_int(val, def, op) char *val; @@ -661,9 +695,9 @@ logfac2str(n) for (fac = facilities; fac->name && fac->num != n; fac++) ; - return (fac->name); + return(fac->name); #else - return ("default"); + return("default"); #endif /* LOG_NFACILITIES */ } @@ -695,7 +729,7 @@ logpri2str(n) for (pri = priorities; pri->name && pri->num != n; pri++) ; - return (pri->name); + return(pri->name); } static int diff --git a/defaults.h b/defaults.h index a30948c..aac0136 100644 --- a/defaults.h +++ b/defaults.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 1999-2001 Todd C. Miller + * Copyright (c) 1999-2005, 2008 + * 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 @@ -17,7 +18,7 @@ * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. * - * $Sudo: defaults.h,v 1.28 2004/02/13 21:36:43 millert Exp $ + * $Sudo: defaults.h,v 1.33 2008/11/09 14:13:12 millert Exp $ */ #ifndef _SUDO_DEFAULTS_H @@ -90,12 +91,23 @@ struct sudo_defs_types { #undef T_PATH #define T_PATH 0x200 +/* + * Argument to update_defaults() + */ +#define SETDEF_GENERIC 0x01 +#define SETDEF_HOST 0x02 +#define SETDEF_USER 0x04 +#define SETDEF_RUNAS 0x08 +#define SETDEF_CMND 0x10 +#define SETDEF_ALL (SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER|SETDEF_RUNAS|SETDEF_CMND) + /* * Prototypes */ void dump_default __P((void)); int set_default __P((char *, char *, int)); void init_defaults __P((void)); +int update_defaults __P((int)); void list_options __P((void)); extern struct sudo_defs_types sudo_defs_table[]; diff --git a/emul/charclass.h b/emul/charclass.h new file mode 100644 index 0000000..bbe1d9e --- /dev/null +++ b/emul/charclass.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2008 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. + * + * $Sudo: charclass.h,v 1.3 2008/12/09 20:55:50 millert Exp $ + */ + +/* + * POSIX character class support for fnmatch() and glob(). + */ +static struct cclass { + const char *name; + int (*isctype) __P((int)); +} cclasses[] = { + { "alnum", isalnum }, + { "alpha", isalpha }, + { "blank", isblank }, + { "cntrl", iscntrl }, + { "digit", isdigit }, + { "graph", isgraph }, + { "lower", islower }, + { "print", isprint }, + { "punct", ispunct }, + { "space", isspace }, + { "upper", isupper }, + { "xdigit", isxdigit }, + { NULL, NULL } +}; + +#define NCCLASSES (sizeof(cclasses) / sizeof(cclasses[0]) - 1) diff --git a/emul/err.h b/emul/err.h deleted file mode 100644 index 637740b..0000000 --- a/emul/err.h +++ /dev/null @@ -1,69 +0,0 @@ -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)err.h 8.1 (Berkeley) 6/2/93 - */ - -#ifndef _ERR_H_ -#define _ERR_H_ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 5 -#define __attribute__(x) -#endif - -#ifdef __STDC__ -void err(int, const char *, ...) __attribute__((__noreturn__)); -void verr(int, const char *, va_list) __attribute__((__noreturn__)); -void errx(int, const char *, ...) __attribute__((__noreturn__)); -void verrx(int, const char *, va_list) __attribute__((__noreturn__)); -void warn(const char *, ...); -void vwarn(const char *, va_list); -void warnx(const char *, ...); -void vwarnx(const char *, va_list); -#else -void err() __attribute__((__noreturn__)); -void verr() __attribute__((__noreturn__)); -void errx() __attribute__((__noreturn__)); -void verrx() __attribute__((__noreturn__)); -void warn(); -void vwarn(); -void warnx(); -void vwarnx(); -#endif /* __STDC__ */ - -#endif /* !_ERR_H_ */ diff --git a/emul/fnmatch.h b/emul/fnmatch.h index 7a66a46..9f65bc5 100644 --- a/emul/fnmatch.h +++ b/emul/fnmatch.h @@ -10,11 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -44,8 +40,6 @@ #define FNM_PERIOD 0x04 /* Period must be matched by period. */ #define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ #define FNM_CASEFOLD 0x10 /* Case insensitive search. */ -#define FNM_IGNORECASE FNM_CASEFOLD -#define FNM_FILE_NAME FNM_PATHNAME int fnmatch __P((const char *, const char *, int)); diff --git a/emul/search.h b/emul/search.h deleted file mode 100644 index 4123e2a..0000000 --- a/emul/search.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 1999 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. - * - * $Sudo: search.h,v 1.9 2004/02/13 21:36:49 millert Exp $ - */ - -#ifndef _SEARCH_H -#define _SEARCH_H - -VOID *lfind __P((const VOID *, const VOID *, size_t *, size_t, - int (*)(const VOID *, const VOID *))); -VOID *lsearch __P((const VOID *, const VOID *, size_t *, size_t, - int (*)(const VOID *, const VOID *))); - -#endif /* _SEARCH_H */ diff --git a/emul/timespec.h b/emul/timespec.h index 66580eb..2951842 100644 --- a/emul/timespec.h +++ b/emul/timespec.h @@ -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: timespec.h,v 1.1.2.1 2007/06/11 11:27:37 millert Exp $ + * $Sudo: timespec.h,v 1.1 2005/06/23 03:04:35 millert Exp $ */ #ifndef _SUDO_TIMESPEC_H diff --git a/env.c b/env.c index dba4955..af6d535 100644 --- a/env.c +++ b/env.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2000-2007 Todd C. Miller + * Copyright (c) 2000-2005, 2007-2008 + * 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 @@ -42,17 +43,12 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: env.c,v 1.39.2.19 2008/06/21 19:04:07 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: env.c,v 1.94 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ /* @@ -93,7 +89,7 @@ __unused static const char rcsid[] = "$Sudo: env.c,v 1.39.2.19 2008/06/21 19:04: #define KEPT_MAX 0xff00 #undef VNULL -#define VNULL (VOID *)NULL +#define VNULL (void *)NULL struct environment { char **envp; /* pointer to the new environment */ @@ -104,9 +100,14 @@ struct environment { /* * Prototypes */ -char **rebuild_env __P((char **, int, int)); -static void insert_env __P((char *, struct environment *, int)); -static char *format_env __P((char *, ...)); +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)); + +extern char **environ; /* global environment */ /* * Copy of the sudo-managed environment. @@ -133,6 +134,7 @@ static const char *initial_badenv_table[] = { #ifdef _AIX "LDR_*", "LIBPATH", + "AUTHSTATE", #endif #ifdef __APPLE__ "DYLD_*", @@ -213,86 +215,150 @@ static const char *initial_keepenv_table[] = { }; /* - * Given a variable and value, allocate and format an environment string. + * Syncronize our private copy of the environment with what is + * in environ. */ -static char * -#ifdef __STDC__ -format_env(char *var, ...) -#else -format_env(var, va_alist) - char *var; - va_dcl -#endif +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. + */ +static void +_sudo_setenv(var, val, dupcheck) + const char *var; + const char *val; + int dupcheck; { char *estring; - char *val; size_t esize; - va_list ap; -#ifdef __STDC__ - va_start(ap, var); -#else - va_start(ap); -#endif - esize = strlen(var) + 2; - while ((val = va_arg(ap, char *)) != NULL) - esize += strlen(val); - va_end(ap); - estring = (char *) emalloc(esize); + esize = strlen(var) + 1 + strlen(val) + 1; + estring = emalloc(esize); - /* Store variable name and the '=' separator. */ + /* Build environment string and insert it. */ if (strlcpy(estring, var, esize) >= esize || - strlcat(estring, "=", esize) >= esize) { + strlcat(estring, "=", esize) >= esize || + strlcat(estring, val, esize) >= esize) { - errx(1, "internal error, format_env() overflow"); + errorx(1, "internal error, sudo_setenv() overflow"); } + insert_env(estring, dupcheck, FALSE); +} - /* Now store the variable's value (if any) */ -#ifdef __STDC__ - va_start(ap, var); -#else - va_start(ap); -#endif - while ((val = va_arg(ap, char *)) != NULL) { - if (strlcat(estring, val, esize) >= esize) - errx(1, "internal error, format_env() overflow"); +#ifdef HAVE_LDAP +/* + * External version of sudo_setenv() that keeps things in sync with + * the environ pointer. + */ +void +sudo_setenv(var, val, dupcheck) + const char *var; + const char *val; + int dupcheck; +{ + char *estring; + size_t esize; + + /* Make sure we are operating on the current environment. */ + if (env.envp != environ) + sync_env(); + + esize = strlen(var) + 1 + strlen(val) + 1; + estring = emalloc(esize); + + /* Build environment string and insert it. */ + if (strlcpy(estring, var, esize) >= esize || + strlcat(estring, "=", esize) >= esize || + strlcat(estring, val, esize) >= esize) { + + errorx(1, "internal error, sudo_setenv() overflow"); } - va_end(ap); + insert_env(estring, dupcheck, TRUE); +} +#endif /* HAVE_LDAP */ + +#if defined(HAVE_LDAP) || defined(HAVE_AIXAUTH) +/* + * Similar to unsetenv(3) but operates on sudo's private copy of the + * environment. + */ +void +sudo_unsetenv(var) + const char *var; +{ + char **nep; + size_t varlen; - return(estring); + /* 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 *)); + env.env_len--; + return; + } + } } +#endif /* HAVE_LDAP || HAVE_AIXAUTH */ /* - * Insert str into e->envp, assumes str has an '=' in it. + * Insert str into env.envp, assumes str has an '=' in it. */ static void -insert_env(str, e, dupcheck) +insert_env(str, dupcheck, dosync) char *str; - struct environment *e; int dupcheck; + int dosync; { char **nep; size_t varlen; /* Make sure there is room for the new entry plus a NULL. */ - if (e->env_len + 2 > e->env_size) { - e->env_size += 128; - e->envp = erealloc3(e->envp, e->env_size, sizeof(char *)); + 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; } if (dupcheck) { varlen = (strchr(str, '=') - str) + 1; - for (nep = e->envp; *nep; nep++) { + for (nep = env.envp; *nep; nep++) { if (strncmp(str, *nep, varlen) == 0) { - *nep = str; + if (dupcheck != -1) + *nep = str; return; } } } else - nep = e->envp + e->env_len; + nep = env.envp + env.env_len; - e->env_len++; + env.env_len++; *nep++ = str; *nep = NULL; } @@ -391,13 +457,13 @@ matches_env_keep(var) * variables from the old one or start with a clean slate. * Also adds sudo-specific variables (SUDO_*). */ -char ** -rebuild_env(envp, sudo_mode, noexec) - char **envp; +void +rebuild_env(sudo_mode, noexec) int sudo_mode; int noexec; { - char **ep, *cp, *ps1; + char **old_envp, **ep, *cp, *ps1; + char idbuf[MAX_UID_T_LEN]; unsigned int didvar; /* @@ -405,10 +471,13 @@ rebuild_env(envp, sudo_mode, noexec) */ ps1 = NULL; didvar = 0; - memset(&env, 0, sizeof(env)); + env.env_len = 0; + env.env_size = 128; + old_envp = env.envp; + env.envp = emalloc2(env.env_size, sizeof(char *)); if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) { /* Pull in vars we want to keep from the old environment. */ - for (ep = envp; *ep; ep++) { + for (ep = environ; *ep; ep++) { int keepit; /* Skip variables with values beginning with () (bash functions) */ @@ -460,7 +529,7 @@ rebuild_env(envp, sudo_mode, noexec) SET(didvar, DID_USERNAME); break; } - insert_env(*ep, &env, 0); + insert_env(*ep, FALSE, FALSE); } } didvar |= didvar << 8; /* convert DID_* to KEPT_* */ @@ -471,35 +540,31 @@ rebuild_env(envp, sudo_mode, noexec) * on sudoers options). */ if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { - insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), &env, - ISSET(didvar, DID_HOME)); - insert_env(format_env("SHELL", runas_pw->pw_shell, VNULL), &env, - ISSET(didvar, DID_SHELL)); - insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), &env, + _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)); - insert_env(format_env("USER", runas_pw->pw_name, VNULL), &env, - ISSET(didvar, DID_USER)); - insert_env(format_env("USERNAME", runas_pw->pw_name, VNULL), &env, + _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)) - insert_env(format_env("HOME", user_dir, VNULL), &env, 0); + _sudo_setenv("HOME", user_dir, FALSE); if (!ISSET(didvar, DID_SHELL)) - insert_env(format_env("SHELL", sudo_user.pw->pw_shell, VNULL), - &env, 0); + _sudo_setenv("SHELL", sudo_user.pw->pw_shell, FALSE); if (!ISSET(didvar, DID_LOGNAME)) - insert_env(format_env("LOGNAME", user_name, VNULL), &env, 0); + _sudo_setenv("LOGNAME", user_name, FALSE); if (!ISSET(didvar, DID_USER)) - insert_env(format_env("USER", user_name, VNULL), &env, 0); + _sudo_setenv("USER", user_name, FALSE); if (!ISSET(didvar, DID_USERNAME)) - insert_env(format_env("USERNAME", user_name, VNULL), &env, 0); + _sudo_setenv("USERNAME", user_name, FALSE); } } else { /* - * Copy envp entries as long as they don't match env_delete or + * Copy environ entries as long as they don't match env_delete or * env_check. */ - for (ep = envp; *ep; ep++) { + for (ep = environ; *ep; ep++) { int okvar; /* Skip variables with values beginning with () (bash functions) */ @@ -523,28 +588,25 @@ rebuild_env(envp, sudo_mode, noexec) SET(didvar, DID_PATH); else if (strncmp(*ep, "TERM=", 5) == 0) SET(didvar, DID_TERM); - insert_env(*ep, &env, 0); + insert_env(*ep, FALSE, FALSE); } } } - -#ifdef SECURE_PATH - /* Replace the PATH envariable with a secure one. */ - if (!user_is_exempt()) { - insert_env(format_env("PATH", SECURE_PATH, VNULL), &env, 1); + /* Replace the PATH envariable with a secure one? */ + if (def_secure_path && !user_is_exempt()) { + _sudo_setenv("PATH", def_secure_path, TRUE); SET(didvar, DID_PATH); } -#endif /* Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is true. */ /* XXX - not needed for MODE_LOGIN_SHELL */ if (def_set_logname && runas_pw->pw_name) { if (!ISSET(didvar, KEPT_LOGNAME)) - insert_env(format_env("LOGNAME", runas_pw->pw_name, VNULL), &env, 1); + _sudo_setenv("LOGNAME", runas_pw->pw_name, TRUE); if (!ISSET(didvar, KEPT_USER)) - insert_env(format_env("USER", runas_pw->pw_name, VNULL), &env, 1); + _sudo_setenv("USER", runas_pw->pw_name, TRUE); if (!ISSET(didvar, KEPT_USERNAME)) - insert_env(format_env("USERNAME", runas_pw->pw_name, VNULL), &env, 1); + _sudo_setenv("USERNAME", runas_pw->pw_name, TRUE); } /* Set $HOME for `sudo -H'. Only valid at PERM_FULL_RUNAS. */ @@ -553,14 +615,14 @@ rebuild_env(envp, 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)))) - insert_env(format_env("HOME", runas_pw->pw_dir, VNULL), &env, 1); + _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", &env, 0); + insert_env("TERM=unknown", FALSE, FALSE); if (!ISSET(didvar, DID_PATH)) - insert_env(format_env("PATH", _PATH_DEFPATH, VNULL), &env, 0); + _sudo_setenv("PATH", _PATH_DEFPATH, FALSE); /* * Preload a noexec file? For a list of LD_PRELOAD-alikes, see @@ -569,78 +631,63 @@ rebuild_env(envp, sudo_mode, noexec) */ if (noexec && def_noexec_file != NULL) { #if defined(__darwin__) || defined(__APPLE__) - insert_env(format_env("DYLD_INSERT_LIBRARIES", def_noexec_file, VNULL), - &env, 1); - insert_env(format_env("DYLD_FORCE_FLAT_NAMESPACE", VNULL), &env, 1); + _sudo_setenv("DYLD_INSERT_LIBRARIES", def_noexec_file, TRUE); + _sudo_setenv("DYLD_FORCE_FLAT_NAMESPACE", "", TRUE); #else # if defined(__osf__) || defined(__sgi) - insert_env(format_env("_RLD_LIST", def_noexec_file, ":DEFAULT", VNULL), - &env, 1); + easprintf(&cp, "%s:DEFAULT", def_noexec_file); + _sudo_setenv("_RLD_LIST", cp, TRUE); + efree(cp); # else # ifdef _AIX - insert_env(format_env("LDR_PRELOAD", def_noexec_file, VNULL), &env, 1); + _sudo_setenv("LDR_PRELOAD", def_noexec_file, TRUE); # else - insert_env(format_env("LD_PRELOAD", def_noexec_file, VNULL), &env, 1); + _sudo_setenv("LD_PRELOAD", def_noexec_file, TRUE); # endif /* _AIX */ # endif /* __osf__ || __sgi */ #endif /* __darwin__ || __APPLE__ */ } /* Set PS1 if SUDO_PS1 is set. */ - if (ps1) - insert_env(ps1, &env, 1); + if (ps1 != NULL) + insert_env(ps1, TRUE, FALSE); /* Add the SUDO_COMMAND envariable (cmnd + args). */ - if (user_args) - insert_env(format_env("SUDO_COMMAND", user_cmnd, " ", user_args, VNULL), - &env, 1); - else - insert_env(format_env("SUDO_COMMAND", user_cmnd, VNULL), &env, 1); + if (user_args) { + easprintf(&cp, "%s %s", user_cmnd, user_args); + _sudo_setenv("SUDO_COMMAND", cp, TRUE); + efree(cp); + } else + _sudo_setenv("SUDO_COMMAND", user_cmnd, TRUE); /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */ - insert_env(format_env("SUDO_USER", user_name, VNULL), &env, 1); - easprintf(&cp, "SUDO_UID=%lu", (unsigned long) user_uid); - insert_env(cp, &env, 1); - easprintf(&cp, "SUDO_GID=%lu", (unsigned long) user_gid); - insert_env(cp, &env, 1); - - return(env.envp); + _sudo_setenv("SUDO_USER", user_name, TRUE); + snprintf(idbuf, sizeof(idbuf), "%lu", (unsigned long) user_uid); + _sudo_setenv("SUDO_UID", idbuf, TRUE); + snprintf(idbuf, sizeof(idbuf), "%lu", (unsigned long) user_gid); + _sudo_setenv("SUDO_GID", idbuf, TRUE); + + /* Install new environment. */ + environ = env.envp; + efree(old_envp); } -char ** -insert_env_vars(envp, env_vars) - char **envp; +void +insert_env_vars(env_vars) struct list_member *env_vars; { struct list_member *cur; if (env_vars == NULL) - return (envp); + return; - /* - * Make sure we still own the environment and steal it back if not. - */ - if (env.envp != envp) { - size_t evlen; - char **ep; - - for (ep = envp; *ep != NULL; ep++) - continue; - evlen = ep - envp; - 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, envp, (evlen + 1) * sizeof(char *)); - env.env_len = evlen; - } + /* 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, &env, 1); - - return(env.envp); + insert_env(cur->value, TRUE, TRUE); } /* @@ -658,12 +705,10 @@ validate_env_vars(env_vars) int okvar; for (var = env_vars; var != NULL; var = var->next) { -#ifdef SECURE_PATH - if (!user_is_exempt() && strncmp(var->value, "PATH=", 5) == 0) { + if (def_secure_path && !user_is_exempt() && + strncmp(var->value, "PATH=", 5) == 0) { okvar = FALSE; - } else -#endif - if (def_env_reset) { + } else if (def_env_reset) { okvar = matches_env_check(var->value); if (okvar == -1) okvar = matches_env_keep(var->value); @@ -700,6 +745,41 @@ validate_env_vars(env_vars) } } +/* + * Read in /etc/environment ala AIX and Linux. + * Lines are in the form of NAME=VALUE + * Invalid lines, blank lines, or lines consisting solely of a comment + * character are skipped. + */ +void +read_env_file(path, replace) + const char *path; + int replace; +{ + FILE *fp; + char *cp; + + 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) { + /* Skip blank or comment lines */ + if (*cp == '\0') + continue; + + /* Must be of the form name=value */ + if (strchr(cp, '=') == NULL) + continue; + + insert_env(estrdup(cp), replace ? TRUE : -1, TRUE); + } + fclose(fp); +} + void init_envtables() { diff --git a/err.c b/err.c deleted file mode 100644 index e9a37f6..0000000 --- a/err.c +++ /dev/null @@ -1,183 +0,0 @@ -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)err.c 8.1 (Berkeley) 6/4/93" - */ - -#include -#include -#include -#include - -#include -#include -#include "emul/err.h" - -#ifndef lint -__unused static const char rcsid[] = "$Sudo: err.c,v 1.2.2.1 2007/06/12 00:56:42 millert Exp $"; -#endif /* lint */ - -void -#ifdef __STDC__ -err(int eval, const char *fmt, ...) -#else -err(eval, fmt, va_alist) - int eval; - const char *fmt; - va_dcl -#endif -{ - va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - verr(eval, fmt, ap); - va_end(ap); -} - -void -verr(eval, fmt, ap) - int eval; - const char *fmt; - va_list ap; -{ - int sverrno; - - sverrno = errno; - (void)fprintf(stderr, "%s: ", getprogname()); - if (fmt != NULL) { - (void)vfprintf(stderr, fmt, ap); - (void)fprintf(stderr, ": "); - } - (void)fprintf(stderr, "%s\n", strerror(sverrno)); - exit(eval); -} - -void -#ifdef __STDC__ -errx(int eval, const char *fmt, ...) -#else -errx(eval, fmt, va_alist) - int eval; - const char *fmt; - va_dcl -#endif -{ - va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - verrx(eval, fmt, ap); - va_end(ap); -} - -void -verrx(eval, fmt, ap) - int eval; - const char *fmt; - va_list ap; -{ - (void)fprintf(stderr, "%s: ", getprogname()); - if (fmt != NULL) - (void)vfprintf(stderr, fmt, ap); - (void)fprintf(stderr, "\n"); - exit(eval); -} - -void -#ifdef __STDC__ -warn(const char *fmt, ...) -#else -warn(fmt, va_alist) - const char *fmt; - va_dcl -#endif -{ - va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - vwarn(fmt, ap); - va_end(ap); -} - -void -vwarn(fmt, ap) - const char *fmt; - va_list ap; -{ - int sverrno; - - sverrno = errno; - (void)fprintf(stderr, "%s: ", getprogname()); - if (fmt != NULL) { - (void)vfprintf(stderr, fmt, ap); - (void)fprintf(stderr, ": "); - } - (void)fprintf(stderr, "%s\n", strerror(sverrno)); -} - -void -#ifdef __STDC__ -warnx(const char *fmt, ...) -#else -warnx(fmt, va_alist) - const char *fmt; - va_dcl -#endif -{ - va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - vwarnx(fmt, ap); - va_end(ap); -} - -void -vwarnx(fmt, ap) - const char *fmt; - va_list ap; -{ - (void)fprintf(stderr, "%s: ", getprogname()); - if (fmt != NULL) - (void)vfprintf(stderr, fmt, ap); - (void)fprintf(stderr, "\n"); -} diff --git a/error.c b/error.c new file mode 100644 index 0000000..6f8149b --- /dev/null +++ b/error.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2004-2005 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 + +#include +#include +#include "error.h" + +#ifndef lint +__unused static const char rcsid[] = "$Sudo: error.c,v 1.7 2005/11/18 01:39:58 millert Exp $"; +#endif /* lint */ + +static void _warning __P((int, const char *, va_list)); + void cleanup __P((int)); + +void +#ifdef __STDC__ +error(int eval, const char *fmt, ...) +#else +error(eval, fmt, va_alist) + int eval; + const char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + _warning(1, fmt, ap); + va_end(ap); + cleanup(0); + exit(eval); +} + +void +#ifdef __STDC__ +errorx(int eval, const char *fmt, ...) +#else +errorx(eval, fmt, va_alist) + int eval; + const char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + _warning(0, fmt, ap); + va_end(ap); + cleanup(0); + exit(eval); +} + +void +#ifdef __STDC__ +warning(const char *fmt, ...) +#else +warning(fmt, va_alist) + const char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + _warning(1, fmt, ap); + va_end(ap); +} + +void +#ifdef __STDC__ +warningx(const char *fmt, ...) +#else +warningx(fmt, va_alist) + const char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + _warning(0, fmt, ap); + va_end(ap); +} + +static void +_warning(use_errno, fmt, ap) + int use_errno; + const char *fmt; + va_list ap; +{ + int serrno = errno; + + fputs(getprogname(), stderr); + if (fmt != NULL) { + fputs(": ", stderr); + vfprintf(stderr, fmt, ap); + } + if (use_errno) { + fputs(": ", stderr); + fputs(strerror(serrno), stderr); + } + putc('\n', stderr); +} diff --git a/error.h b/error.h new file mode 100644 index 0000000..e8d7b77 --- /dev/null +++ b/error.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2004 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. + * + * $Sudo: error.h,v 1.2 2004/11/19 17:32:25 millert Exp $ + */ + +#ifndef _SUDO_ERROR_H_ +#define _SUDO_ERROR_H_ + +#ifdef __STDC__ +# include +void error(int, const char *, ...) __attribute__((__noreturn__)); +void errorx(int, const char *, ...) __attribute__((__noreturn__)); +void warning(const char *, ...); +void warningx(const char *, ...); +#else +# include +void error() __attribute__((__noreturn__)); +void errorx() __attribute__((__noreturn__)); +void warning(); +void warningx(); +#endif /* __STDC__ */ + +#endif /* _SUDO_ERROR_H_ */ diff --git a/fileops.c b/fileops.c index e15c512..9f176bd 100644 --- a/fileops.c +++ b/fileops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2007 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 @@ -27,6 +27,15 @@ # include #endif /* HAVE_FLOCK */ #include +#ifdef HAVE_STRING_H +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#include +#include #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ @@ -40,8 +49,12 @@ #include "sudo.h" +#ifndef LINE_MAX +# define LINE_MAX 2048 +#endif + #ifndef lint -__unused static const char rcsid[] = "$Sudo: fileops.c,v 1.5.2.5 2007/06/12 01:28:41 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: fileops.c,v 1.16 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ /* @@ -139,3 +152,30 @@ lock_file(fd, lockit) #endif } #endif + +/* + * Read a line of input, remove comments and strip off leading + * and trailing spaces. Returns static storage that is reused. + */ +char * +sudo_parseln(fp) + FILE *fp; +{ + size_t len; + char *cp = NULL; + static char buf[LINE_MAX]; + + if (fgets(buf, sizeof(buf), fp) != NULL) { + /* Remove comments */ + if ((cp = strchr(buf, '#')) != NULL) + *cp = '\0'; + + /* Trim leading and trailing whitespace/newline */ + len = strlen(buf); + while (len > 0 && isspace(buf[len - 1])) + buf[--len] = '\0'; + for (cp = buf; isblank(*cp); cp++) + continue; + } + return(cp); +} diff --git a/find_path.c b/find_path.c index 3fcf314..673cd0d 100644 --- a/find_path.c +++ b/find_path.c @@ -42,16 +42,11 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: find_path.c,v 1.108.2.4 2007/06/12 01:43:01 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: find_path.c,v 1.115 2005/03/29 14:29:46 millert Exp $"; #endif /* lint */ /* @@ -76,7 +71,7 @@ find_path(infile, outfile, sbp, path) int len; /* length parameter */ if (strlen(infile) >= PATH_MAX) - errx(1, "%s: File name too long", infile); + errorx(1, "%s: File name too long", infile); /* * If we were given a fully qualified or relative path @@ -92,11 +87,9 @@ find_path(infile, outfile, sbp, path) } /* Use PATH passed in unless SECURE_PATH is in effect. */ -#ifdef SECURE_PATH - if (!user_is_exempt()) - path = SECURE_PATH; -#endif /* SECURE_PATH */ - if (path == NULL) + if (def_secure_path && !user_is_exempt()) + path = def_secure_path; + else if (path == NULL) return(NOT_FOUND); path = estrdup(path); origpath = path; @@ -120,7 +113,7 @@ find_path(infile, outfile, sbp, path) */ len = snprintf(command, sizeof(command), "%s/%s", path, infile); if (len <= 0 || len >= sizeof(command)) - errx(1, "%s: File name too long", infile); + errorx(1, "%s: File name too long", infile); if ((result = sudo_goodpath(command, sbp))) break; diff --git a/fnmatch.3 b/fnmatch.3 deleted file mode 100644 index 652ff93..0000000 --- a/fnmatch.3 +++ /dev/null @@ -1,144 +0,0 @@ -.\" $OpenBSD: fnmatch.3,v 1.7 1999/06/05 04:47:41 aaron Exp $ -.\" -.\" Copyright (c) 1989, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" Guido van Rossum. -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)fnmatch.3 8.3 (Berkeley) 4/28/95 -.\" -.Dd April 28, 1995 -.Dt FNMATCH 3 -.Os -.Sh NAME -.Nm fnmatch -.Nd match filename or pathname using shell globbing rules -.Sh SYNOPSIS -.Fd #include -.Ft int -.Fn fnmatch "const char *pattern" "const char *string" "int flags" -.Sh DESCRIPTION -The -.Fn fnmatch -function -matches patterns according to the globbing rules used by the shell. -It checks the string specified by the -.Fa string -argument to see if it matches the pattern specified by the -.Fa pattern -argument. -.Pp -The -.Fa flags -argument modifies the interpretation of -.Fa pattern -and -.Fa string . -The value of -.Fa flags -is the bitwise inclusive -.Tn OR -of any of the following -constants, which are defined in the include file -.Aq Pa fnmatch.h . -.Bl -tag -width FNM_PATHNAME -.It Dv FNM_NOESCAPE -Normally, every occurrence of a backslash -.Pq Sq \e -followed by a character in -.Fa pattern -is replaced by that character. -This is done to negate any special meaning for the character. -If the -.Dv FNM_NOESCAPE -flag is set, a backslash character is treated as an ordinary character. -.It Dv FNM_PATHNAME -Slash characters in -.Fa string -must be explicitly matched by slashes in -.Fa pattern . -If this flag is not set, then slashes are treated as regular characters. -.It Dv FNM_PERIOD -Leading periods in -.Fa string -must be explicitly matched by periods in -.Fa pattern . -If this flag is not set, then leading periods are treated as regular -characters. -The definition of -.Dq leading -is related to the specification of -.Dv FNM_PATHNAME . -A period is always leading -if it is the first character in -.Fa string . -Additionally, if -.Dv FNM_PATHNAME -is set, -a period is leading -if it immediately follows a slash. -.It Dv FNM_LEADING_DIR -Ignore -.Nm /* -rest after successful -.Fa pattern -matching. -.It Dv FNM_CASEFOLD -Ignore case distinctions in both the -.Fa pattern -and the -.Fa string . -.El -.Sh RETURN VALUES -The -.Fn fnmatch -function returns zero if -.Fa string -matches the pattern specified by -.Fa pattern , -otherwise, it returns the value -.Dv FNM_NOMATCH . -.Sh SEE ALSO -.Xr sh 1 , -.Xr glob 3 , -.Xr regex 3 -.Sh STANDARDS -The -.Fn fnmatch -function conforms to -.St -p1003.2-92 . -.Sh HISTORY -The -.Fn fnmatch -function first appeared in -.Bx 4.4 . -.Sh BUGS -The pattern -.Ql * -matches the empty string, even if -.Dv FNM_PATHNAME -is specified. diff --git a/fnmatch.c b/fnmatch.c index bacff5d..625d759 100644 --- a/fnmatch.c +++ b/fnmatch.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2008 Todd C. Miller * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * @@ -49,6 +50,7 @@ #include #include "emul/fnmatch.h" +#include "emul/charclass.h" #undef EOS #define EOS '\0' @@ -58,10 +60,11 @@ #define RANGE_ERROR (-1) #if defined(LIBC_SCCS) && !defined(lint) -__unused static char rcsid[] = "$OpenBSD: fnmatch.c,v 1.6 1998/03/19 00:29:59 millert Exp $"; +__unused static const char rcsid[] = "$OpenBSD: fnmatch.c,v 1.6 1998/03/19 00:29:59 millert Exp $"; #endif /* LIBC_SCCS and not lint */ -static int rangematch __P((const char *, char, int, char **)); +static int rangematch __P((const char *, int, int, char **)); +static int classmatch __P((const char *, int, int, const char **)); int fnmatch(pattern, string, flags) @@ -167,16 +170,16 @@ fnmatch(pattern, string, flags) static int #ifdef __STDC__ -rangematch(const char *pattern, char test, int flags, char **newp) +rangematch(const char *pattern, int test, int flags, char **newp) #else rangematch(pattern, test, flags, newp) const char *pattern; - char test; + int test; int flags; char **newp; #endif { - int negate, ok; + int negate, ok, rv; char c, c2; /* @@ -190,7 +193,7 @@ rangematch(pattern, test, flags, newp) ++pattern; if (ISSET(flags, FNM_CASEFOLD)) - test = tolower((unsigned char)test); + test = tolower(test); /* * A right bracket shall lose its special meaning and represent @@ -200,6 +203,17 @@ rangematch(pattern, test, flags, newp) ok = 0; c = *pattern++; do { + if (c == '[' && *pattern == ':') { + do { + rv = classmatch(pattern + 1, test, + (flags & FNM_CASEFOLD), &pattern); + if (rv == RANGE_MATCH) + ok = 1; + c = *pattern++; + } while (rv != RANGE_ERROR && c == '[' && *pattern == ':'); + if (c == ']') + break; + } if (c == '\\' && !ISSET(flags, FNM_NOESCAPE)) c = *pattern++; if (c == EOS) @@ -226,3 +240,43 @@ rangematch(pattern, test, flags, newp) *newp = (char *)pattern; return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH); } + +static int +#ifdef __STDC__ +classmatch(const char *pattern, int test, int foldcase, const char **ep) +#else +classmatch(pattern, test, foldcase, ep) + const char *pattern; + int test; + int foldcase; + const char **ep; +#endif +{ + struct cclass *cc; + const char *colon; + size_t len; + int rval = RANGE_NOMATCH; + + if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') { + *ep = pattern - 2; + return(RANGE_ERROR); + } + *ep = colon + 2; + len = (size_t)(colon - pattern); + + if (foldcase && strncmp(pattern, "upper:]", 7) == 0) + pattern = "lower:]"; + for (cc = cclasses; cc->name != NULL; cc++) { + if (!strncmp(pattern, cc->name, len) && cc->name[len] == '\0') { + if (cc->isctype(test)) + rval = RANGE_MATCH; + break; + } + } + if (cc->name == NULL) { + /* invalid character class, return EOS */ + *ep = colon + strlen(colon); + rval = RANGE_ERROR; + } + return(rval); +} diff --git a/getcwd.c b/getcwd.c index 0478932..6b5588a 100644 --- a/getcwd.c +++ b/getcwd.c @@ -79,7 +79,7 @@ (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) #ifndef lint -__unused static const char rcsid[] = "$Sudo: getcwd.c,v 1.25.2.1 2007/06/12 00:56:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: getcwd.c,v 1.28 2005/02/08 03:55:42 millert Exp $"; #endif /* lint */ char * diff --git a/getprogname.c b/getprogname.c index 387416d..bd06d0e 100644 --- a/getprogname.c +++ b/getprogname.c @@ -25,7 +25,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: getprogname.c,v 1.4.2.2 2007/06/12 01:28:41 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: getprogname.c,v 1.7 2005/02/12 22:56:06 millert Exp $"; #endif /* lint */ const char * diff --git a/getspwuid.c b/getspwuid.c index 07f5308..c6848a7 100644 --- a/getspwuid.c +++ b/getspwuid.c @@ -46,6 +46,7 @@ # include #endif /* HAVE_UNISTD_H */ #include +#include #ifdef HAVE_GETSPNAM # include #endif /* HAVE_GETSPNAM */ @@ -70,17 +71,16 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: getspwuid.c,v 1.65.2.2 2007/06/12 01:28:41 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: getspwuid.c,v 1.78 2005/02/12 22:56:06 millert Exp $"; #endif /* lint */ /* - * Global variables (yuck) + * Exported for auth/secureware.c */ #if defined(HAVE_GETPRPWNAM) && defined(__alpha) int crypt_type = INT_MAX; #endif /* HAVE_GETPRPWNAM && __alpha */ - /* * Return a copy of the encrypted password for the user described by pw. * If shadow passwords are in use, look in the shadow file. @@ -106,14 +106,12 @@ sudo_getepw(pw) { struct pr_passwd *spw; - setprpwent(); if ((spw = getprpwnam(pw->pw_name)) && spw->ufld.fd_encrypt) { # ifdef __alpha crypt_type = spw->ufld.fd_oldcrypt; # endif /* __alpha */ epw = estrdup(spw->ufld.fd_encrypt); } - endprpwent(); if (epw) return(epw); } @@ -122,10 +120,8 @@ sudo_getepw(pw) { struct spwd *spw; - setspent(); if ((spw = getspnam(pw->pw_name)) && spw->sp_pwdp) epw = estrdup(spw->sp_pwdp); - endspent(); if (epw) return(epw); } @@ -134,10 +130,8 @@ sudo_getepw(pw) { struct s_passwd *spw; - setspwent(); if ((spw = getspwuid(pw->pw_uid)) && spw->pw_passwd) epw = estrdup(spw->pw_passwd); - endspwent(); if (epw) return(epw); } @@ -146,10 +140,8 @@ sudo_getepw(pw) { struct passwd_adjunct *spw; - setpwaent(); if ((spw = getpwanam(pw->pw_name)) && spw->pwa_passwd) epw = estrdup(spw->pwa_passwd); - endpwaent(); if (epw) return(epw); } @@ -158,10 +150,8 @@ sudo_getepw(pw) { AUTHORIZATION *spw; - setauthent(); if ((spw = getauthuid(pw->pw_uid)) && spw->a_password) epw = estrdup(spw->a_password); - endauthent(); if (epw) return(epw); } @@ -171,129 +161,42 @@ sudo_getepw(pw) return(estrdup(pw->pw_passwd)); } -/* - * Dynamically allocate space for a struct password and the constituent parts - * that we care about. Fills in pw_passwd from shadow file if necessary. - */ -struct passwd * -sudo_pwdup(pw) - const struct passwd *pw; +void +sudo_setspent() { - char *cp; - const char *pw_passwd, *pw_shell; - size_t nsize, psize, csize, gsize, dsize, ssize, total; - struct passwd *newpw; - - /* Get shadow password if available. */ - pw_passwd = sudo_getepw(pw); - - /* If shell field is empty, expand to _PATH_BSHELL. */ - pw_shell = (pw->pw_shell == NULL || pw->pw_shell[0] == '\0') - ? _PATH_BSHELL : pw->pw_shell; - - /* Allocate in one big chunk for easy freeing. */ - nsize = psize = csize = gsize = dsize = ssize = 0; - total = sizeof(struct passwd); - if (pw->pw_name) { - nsize = strlen(pw->pw_name) + 1; - total += nsize; - } - if (pw_passwd) { - psize = strlen(pw_passwd) + 1; - total += psize; - } -#ifdef HAVE_LOGIN_CAP_H - if (pw->pw_class) { - csize = strlen(pw->pw_class) + 1; - total += csize; - } +#ifdef HAVE_GETPRPWNAM + setprpwent(); #endif - if (pw->pw_gecos) { - gsize = strlen(pw->pw_gecos) + 1; - total += gsize; - } - if (pw->pw_dir) { - dsize = strlen(pw->pw_dir) + 1; - total += dsize; - } - if (pw_shell) { - ssize = strlen(pw_shell) + 1; - total += ssize; - } - if ((cp = malloc(total)) == NULL) - return (NULL); - newpw = (struct passwd *)cp; - - /* - * Copy in passwd contents and make strings relative to space - * at the end of the buffer. - */ - (void)memcpy(newpw, pw, sizeof(struct passwd)); - cp += sizeof(struct passwd); - if (nsize) { - (void)memcpy(cp, pw->pw_name, nsize); - newpw->pw_name = cp; - cp += nsize; - } - if (psize) { - (void)memcpy(cp, pw_passwd, psize); - newpw->pw_passwd = cp; - cp += psize; - } -#ifdef HAVE_LOGIN_CAP_H - if (csize) { - (void)memcpy(cp, pw->pw_class, csize); - newpw->pw_class = cp; - cp += csize; - } +#ifdef HAVE_GETSPNAM + setspent(); +#endif +#ifdef HAVE_GETSPWUID + setspwent(); +#endif +#ifdef HAVE_GETPWANAM + setpwaent(); +#endif +#ifdef HAVE_GETAUTHUID + setauthent(); #endif - if (gsize) { - (void)memcpy(cp, pw->pw_gecos, gsize); - newpw->pw_gecos = cp; - cp += gsize; - } - if (dsize) { - (void)memcpy(cp, pw->pw_dir, dsize); - newpw->pw_dir = cp; - cp += dsize; - } - if (ssize) { - (void)memcpy(cp, pw_shell, ssize); - newpw->pw_shell = cp; - cp += ssize; - } - - return (newpw); -} - -/* - * Get a password entry by uid and allocate space for it. - * Fills in pw_passwd from shadow file if necessary. - */ -struct passwd * -sudo_getpwuid(uid) - uid_t uid; -{ - struct passwd *pw; - - if ((pw = getpwuid(uid)) == NULL) - return(NULL); - else - return(sudo_pwdup(pw)); } -/* - * Get a password entry by name and allocate space for it. - * Fills in pw_passwd from shadow file if necessary. - */ -struct passwd * -sudo_getpwnam(name) - const char *name; +void +sudo_endspent() { - struct passwd *pw; - - if ((pw = getpwnam(name)) == NULL) - return(NULL); - else - return(sudo_pwdup(pw)); +#ifdef HAVE_GETPRPWNAM + endprpwent(); +#endif +#ifdef HAVE_GETSPNAM + endspent(); +#endif +#ifdef HAVE_GETSPWUID + endspwent(); +#endif +#ifdef HAVE_GETPWANAM + endpwaent(); +#endif +#ifdef HAVE_GETAUTHUID + endauthent(); +#endif } diff --git a/gettime.c b/gettime.c index 2b03f65..c864c9b 100644 --- a/gettime.c +++ b/gettime.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 Todd C. Miller + * Copyright (c) 2004-2005, 2008 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 @@ -29,13 +29,12 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: gettime.c,v 1.6.2.5 2007/06/12 01:28:41 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: gettime.c,v 1.8 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ /* * Get the current time via gettimeofday() for systems with * timespecs in struct stat or, otherwise, using time(). - * XXX - configure check for gettimeofday() - XXX */ int gettime(ts) diff --git a/glob.c b/glob.c index 5319c13..46d883b 100644 --- a/glob.c +++ b/glob.c @@ -1,6 +1,5 @@ -/* $OpenBSD: glob.c,v 1.23 2004/05/18 02:05:52 jfb Exp $ */ - /* + * Copyright (c) 2008 Todd C. Miller * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * @@ -99,6 +98,7 @@ #include #include "emul/glob.h" +#include "emul/charclass.h" #define DOLLAR '$' #define DOT '.' @@ -147,6 +147,7 @@ typedef char Char; #define M_ONE META('?') #define M_RNG META('-') #define M_SET META('[') +#define M_CLASS META(':') #define ismeta(c) (((c)&M_QUOTE) != 0) @@ -154,7 +155,8 @@ static int compare __P((const void *, const void *)); static int g_Ctoc __P((const Char *, char *, unsigned int)); static int g_lstat __P((Char *, struct stat *, glob_t *)); static DIR *g_opendir __P((Char *, glob_t *)); -static Char *g_strchr __P((Char *, int)); +static Char *g_strchr __P((const Char *, int)); +static int g_strncmp __P((const Char *, const char *, size_t)); static int g_stat __P((Char *, struct stat *, glob_t *)); static int glob0 __P((const Char *, glob_t *)); static int glob1 __P((Char *, Char *, glob_t *)); @@ -172,6 +174,9 @@ static int match __P((Char *, Char *, Char *)); static void qprintf __P((const char *, Char *)); #endif +extern struct passwd *sudo_getpwnam __P((const char *)); +extern struct passwd *sudo_getpwuid __P((uid_t)); + int glob(pattern, flags, errfunc, pglob) const char *pattern; @@ -235,7 +240,7 @@ globexp1(pattern, pglob) if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) return glob0(pattern, pglob); - while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) + while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) if (!globexp2(ptr, pattern, pglob, &rv)) return rv; @@ -385,7 +390,7 @@ globtilde(pattern, patbuf, patbuf_len, pglob) * first and then trying the password file */ if ((h = getenv("HOME")) == NULL) { - if ((pwd = getpwuid(getuid())) == NULL) + if ((pwd = sudo_getpwuid(getuid())) == NULL) return pattern; else h = pwd->pw_dir; @@ -394,7 +399,7 @@ globtilde(pattern, patbuf, patbuf_len, pglob) /* * Expand a ~user */ - if ((pwd = getpwnam((char*) patbuf)) == NULL) + if ((pwd = sudo_getpwnam((char*) patbuf)) == NULL) return pattern; else h = pwd->pw_dir; @@ -412,6 +417,52 @@ globtilde(pattern, patbuf, patbuf_len, pglob) return patbuf; } +static int +g_strncmp(s1, s2, n) + const Char *s1; + const char *s2; + size_t n; +{ + int rv = 0; + + while (n--) { + rv = *(Char *)s1 - *(const unsigned char *)s2++; + if (rv) + break; + if (*s1++ == '\0') + break; + } + return rv; +} + +static int +g_charclass(patternp, bufnextp) + const Char **patternp; + Char **bufnextp; +{ + const Char *pattern = *patternp + 1; + Char *bufnext = *bufnextp; + const Char *colon; + struct cclass *cc; + size_t len; + + if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']') + return 1; /* not a character class */ + + len = (size_t)(colon - pattern); + for (cc = cclasses; cc->name != NULL; cc++) { + if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0') + break; + } + if (cc->name == NULL) + return -1; /* invalid character class */ + *bufnext++ = M_CLASS; + *bufnext++ = (Char)(cc - &cclasses[0]); + *bufnextp = bufnext; + *patternp += len + 3; + + return 0; +} /* * The main glob() routine: compiles the pattern (optionally processing @@ -441,7 +492,7 @@ glob0(pattern, pglob) if (c == NOT) ++qpatnext; if (*qpatnext == EOS || - g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { + g_strchr(qpatnext+1, RBRACKET) == NULL) { *bufnext++ = LBRACKET; if (c == NOT) --qpatnext; @@ -452,6 +503,20 @@ glob0(pattern, pglob) *bufnext++ = M_NOT; c = *qpatnext++; do { + if (c == LBRACKET && *qpatnext == ':') { + do { + err = g_charclass(&qpatnext, + &bufnext); + if (err) + break; + c = *qpatnext++; + } while (c == LBRACKET && *qpatnext == ':'); + if (err == -1 && + !(pglob->gl_flags & GLOB_NOCHECK)) + return GLOB_NOMATCH; + if (c == RBRACKET) + break; + } *bufnext++ = CHAR(c); if (*qpatnext == RANGE && (c = qpatnext[1]) != RBRACKET) { @@ -750,6 +815,13 @@ match(name, pat, patend) if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) ++pat; while (((c = *pat++) & M_MASK) != M_END) + if ((c & M_MASK) == M_CLASS) { + int idx = *pat & M_MASK; + if (idx < NCCLASSES && + cclasses[idx].isctype(k)) + ok = 1; + ++pat; + } if ((*pat & M_MASK) == M_RNG) { if (c <= k && k <= pat[1]) ok = 1; @@ -831,12 +903,12 @@ g_stat(fn, sb, pglob) static Char * g_strchr(str, ch) - Char *str; + const Char *str; int ch; { do { if (*str == ch) - return (str); + return ((Char *)str); } while (*str++); return (NULL); } diff --git a/goodpath.c b/goodpath.c index 1b72a66..1529404 100644 --- a/goodpath.c +++ b/goodpath.c @@ -39,7 +39,7 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: goodpath.c,v 1.40.2.3 2007/06/12 01:28:41 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: goodpath.c,v 1.44 2005/02/12 22:56:06 millert Exp $"; #endif /* lint */ /* diff --git a/gram.c b/gram.c new file mode 100644 index 0000000..ed991a7 --- /dev/null +++ b/gram.c @@ -0,0 +1,1619 @@ +#ifndef lint +/*static char yysccsid[] = "from: @(#)yaccpar 1.9 (Berkeley) 02/21/93";*/ +static char yyrcsid[] +#if __GNUC__ >= 2 + __attribute__ ((unused)) +#endif /* __GNUC__ >= 2 */ + = "$OpenBSD: skeleton.c,v 1.29 2008/07/08 15:06:50 otto Exp $"; +#endif +#include +#include +#define YYBYACC 1 +#define YYMAJOR 1 +#define YYMINOR 9 +#define YYLEX yylex() +#define YYEMPTY -1 +#define yyclearin (yychar=(YYEMPTY)) +#define yyerrok (yyerrflag=0) +#define YYRECOVERING() (yyerrflag!=0) +#define YYPREFIX "yy" +#line 2 "gram.y" +/* + * Copyright (c) 1996, 1998-2005, 2007-2008 + * 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. + * + * 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. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__) +# include +#endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */ +#include + +#include "sudo.h" +#include "parse.h" + +#ifndef lint +__unused static const char rcsid[] = "$Sudo: gram.c,v 1.34 2008/11/09 14:15:36 millert Exp $"; +#endif /* lint */ + +/* + * We must define SIZE_MAX for yacc's skeleton.c. + * If there is no SIZE_MAX or SIZE_T_MAX we have to assume that size_t + * could be signed (as it is on SunOS 4.x). + */ +#ifndef SIZE_MAX +# ifdef SIZE_T_MAX +# define SIZE_MAX SIZE_T_MAX +# else +# define SIZE_MAX INT_MAX +# endif /* SIZE_T_MAX */ +#endif /* SIZE_MAX */ + +/* + * Globals + */ +extern int sudolineno; +extern char *sudoers; +int parse_error; +int pedantic = FALSE; +int verbose = FALSE; +int errorlineno = -1; +char *errorfile = NULL; + +struct defaults_list defaults; +struct userspec_list userspecs; + +/* + * Local protoypes + */ +static void add_defaults __P((int, struct member *, struct defaults *)); +static void add_userspec __P((struct member *, struct privilege *)); +static struct defaults *new_default __P((char *, char *, int)); +static struct member *new_member __P((char *, int)); + void yyerror __P((const char *)); + +void +yyerror(s) + const char *s; +{ + /* Save the line the first error occurred on. */ + if (errorlineno == -1) { + errorlineno = sudolineno ? sudolineno - 1 : 0; + errorfile = estrdup(sudoers); + } + if (verbose && s != NULL) { +#ifndef TRACELEXER + (void) fprintf(stderr, ">>> %s: %s near line %d <<<\n", sudoers, s, + sudolineno ? sudolineno - 1 : 0); +#else + (void) fprintf(stderr, "<*> "); +#endif + } + parse_error = TRUE; +} +#line 117 "gram.y" +#ifndef YYSTYPE_DEFINED +#define YYSTYPE_DEFINED +typedef union { + struct cmndspec *cmndspec; + struct defaults *defaults; + struct member *member; + struct runascontainer *runas; + struct privilege *privilege; + struct sudo_command command; + struct cmndtag tag; + struct selinux_info seinfo; + char *string; + int tok; +} YYSTYPE; +#endif /* YYSTYPE_DEFINED */ +#line 151 "y.tab.c" +#define COMMAND 257 +#define ALIAS 258 +#define DEFVAR 259 +#define NTWKADDR 260 +#define NETGROUP 261 +#define USERGROUP 262 +#define WORD 263 +#define DEFAULTS 264 +#define DEFAULTS_HOST 265 +#define DEFAULTS_USER 266 +#define DEFAULTS_RUNAS 267 +#define DEFAULTS_CMND 268 +#define NOPASSWD 269 +#define PASSWD 270 +#define NOEXEC 271 +#define EXEC 272 +#define SETENV 273 +#define NOSETENV 274 +#define ALL 275 +#define COMMENT 276 +#define HOSTALIAS 277 +#define CMNDALIAS 278 +#define USERALIAS 279 +#define RUNASALIAS 280 +#define ERROR 281 +#define TYPE 282 +#define ROLE 283 +#define YYERRCODE 256 +#if defined(__cplusplus) || defined(__STDC__) +const short yylhs[] = +#else +short yylhs[] = +#endif + { -1, + 0, 0, 25, 25, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 4, 4, 3, 3, + 3, 3, 3, 20, 20, 19, 10, 10, 8, 8, + 8, 8, 8, 2, 2, 1, 6, 6, 23, 24, + 22, 22, 22, 22, 22, 17, 17, 18, 18, 18, + 21, 21, 21, 21, 21, 21, 21, 5, 5, 5, + 28, 28, 31, 9, 9, 29, 29, 32, 7, 7, + 30, 30, 33, 27, 27, 34, 13, 13, 11, 11, + 12, 12, 12, 12, 12, 16, 16, 14, 14, 15, + 15, 15, +}; +#if defined(__cplusplus) || defined(__STDC__) +const short yylen[] = +#else +short yylen[] = +#endif + { 2, + 0, 1, 1, 2, 1, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 1, 3, 1, 2, + 3, 3, 3, 1, 3, 3, 1, 2, 1, 1, + 1, 1, 1, 1, 3, 4, 1, 2, 3, 3, + 0, 1, 1, 2, 2, 0, 3, 1, 3, 2, + 0, 2, 2, 2, 2, 2, 2, 1, 1, 1, + 1, 3, 3, 1, 3, 1, 3, 3, 1, 3, + 1, 3, 3, 1, 3, 3, 1, 3, 1, 2, + 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, + 1, 1, +}; +#if defined(__cplusplus) || defined(__STDC__) +const short yydefred[] = +#else +short yydefred[] = +#endif + { 0, + 0, 81, 83, 84, 85, 0, 0, 0, 0, 0, + 82, 5, 0, 0, 0, 0, 0, 0, 77, 79, + 0, 0, 3, 6, 0, 0, 17, 0, 29, 32, + 31, 33, 30, 0, 27, 0, 64, 0, 0, 60, + 59, 58, 0, 37, 69, 0, 0, 0, 61, 0, + 0, 66, 0, 0, 74, 0, 0, 71, 80, 0, + 0, 24, 0, 4, 0, 0, 0, 20, 0, 28, + 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 78, 0, 0, 21, 22, + 23, 18, 65, 70, 0, 62, 0, 67, 0, 75, + 0, 72, 0, 34, 0, 0, 25, 0, 0, 0, + 0, 0, 0, 51, 0, 0, 90, 92, 91, 0, + 86, 88, 0, 0, 47, 35, 0, 0, 0, 44, + 45, 89, 0, 0, 40, 39, 52, 53, 54, 55, + 56, 57, 36, 87, +}; +#if defined(__cplusplus) || defined(__STDC__) +const short yydgoto[] = +#else +short yydgoto[] = +#endif + { 18, + 104, 105, 27, 28, 44, 45, 46, 35, 61, 37, + 19, 20, 21, 121, 122, 123, 106, 110, 62, 63, + 129, 114, 115, 116, 22, 23, 54, 48, 51, 57, + 49, 52, 58, 55, +}; +#if defined(__cplusplus) || defined(__STDC__) +const short yysindex[] = +#else +short yysindex[] = +#endif + { 405, + -266, 0, 0, 0, 0, -9, 463, 510, 510, -2, + 0, 0, -243, -218, -215, -211, -225, 0, 0, 0, + -28, 405, 0, 0, -36, -210, 0, 4, 0, 0, + 0, 0, 0, -231, 0, -33, 0, -25, -25, 0, + 0, 0, -240, 0, 0, -21, -6, -1, 0, 2, + 6, 0, 7, 8, 0, 9, 11, 0, 0, 510, + -22, 0, 13, 0, -203, -201, -198, 0, -9, 0, + 463, 4, 4, 4, 0, -2, 4, 463, -243, -2, + -218, 510, -215, 510, -211, 0, 27, 463, 0, 0, + 0, 0, 0, 0, 28, 0, 30, 0, 31, 0, + 31, 0, 141, 0, 32, -262, 0, -27, -16, 36, + 27, 18, 19, 0, -200, -202, 0, 0, 0, -217, + 0, 0, 39, -27, 0, 0, -177, -175, 250, 0, + 0, 0, -27, 39, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,}; +#if defined(__cplusplus) || defined(__STDC__) +const short yyrindex[] = +#else +short yyrindex[] = +#endif + { 90, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 91, 0, 0, 1, 0, 0, 156, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 181, 0, 0, + 206, 0, 0, 237, 0, 0, 274, 0, 0, 0, + 0, 0, 300, 0, 0, 0, 0, 0, 0, 0, + 0, 326, 352, 378, 0, 0, 430, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -29, 0, 0, 0, + 0, 0, 0, 0, 26, 0, 52, 0, 78, 0, + 104, 0, 0, 0, 130, 442, 0, 0, 51, 0, + -29, 0, 0, 0, 461, 485, 0, 0, 0, 0, + 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0,}; +#if defined(__cplusplus) || defined(__STDC__) +const short yygindex[] = +#else +short yygindex[] = +#endif + { 0, + -18, 0, 29, 15, 56, -73, 16, 63, -5, 34, + 40, 84, 5, -31, -17, -15, 0, 0, 24, 0, + 0, 0, -10, -8, 0, 92, 0, 0, 0, 0, + 37, 38, 33, 41, +}; +#define YYTABLESIZE 785 +#if defined(__cplusplus) || defined(__STDC__) +const short yytable[] = +#else +short yytable[] = +#endif + { 26, + 19, 36, 94, 46, 34, 120, 66, 26, 67, 24, + 71, 26, 38, 39, 47, 60, 40, 41, 60, 112, + 113, 71, 76, 26, 65, 63, 29, 60, 30, 31, + 43, 32, 2, 19, 42, 3, 4, 5, 87, 50, + 117, 124, 53, 33, 19, 118, 56, 69, 68, 11, + 72, 68, 73, 74, 78, 143, 79, 119, 63, 89, + 77, 90, 80, 81, 91, 83, 103, 82, 85, 84, + 88, 71, 95, 76, 60, 111, 125, 76, 127, 128, + 113, 112, 133, 63, 68, 135, 99, 136, 101, 1, + 2, 48, 126, 50, 49, 97, 70, 92, 75, 86, + 59, 144, 132, 73, 93, 131, 130, 109, 134, 68, + 76, 107, 0, 64, 0, 96, 0, 102, 98, 0, + 0, 0, 0, 100, 0, 0, 0, 0, 0, 26, + 0, 0, 0, 0, 0, 76, 73, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, + 0, 73, 26, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 26, 12, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 108, 0, + 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 25, 0, 46, 46, 29, + 117, 30, 31, 25, 32, 118, 8, 25, 10, 46, + 46, 46, 46, 46, 46, 46, 33, 119, 0, 25, + 0, 0, 46, 46, 40, 41, 19, 0, 19, 0, + 0, 19, 19, 19, 19, 19, 19, 19, 19, 8, + 0, 0, 42, 11, 0, 19, 19, 19, 19, 19, + 19, 63, 43, 63, 0, 0, 63, 63, 63, 63, + 63, 63, 63, 63, 0, 0, 0, 0, 0, 7, + 63, 63, 63, 63, 63, 63, 11, 68, 0, 68, + 0, 0, 68, 68, 68, 68, 68, 68, 68, 68, + 0, 0, 0, 0, 0, 15, 68, 68, 68, 68, + 68, 68, 7, 76, 0, 76, 0, 0, 76, 76, + 76, 76, 76, 76, 76, 76, 0, 0, 0, 0, + 0, 13, 76, 76, 76, 76, 76, 76, 15, 73, + 0, 73, 0, 0, 73, 73, 73, 73, 73, 73, + 73, 73, 0, 0, 0, 0, 0, 14, 73, 73, + 73, 73, 73, 73, 13, 26, 0, 26, 0, 0, + 26, 26, 26, 26, 26, 26, 26, 26, 2, 0, + 0, 3, 4, 5, 26, 26, 26, 26, 26, 26, + 14, 12, 0, 12, 0, 11, 12, 12, 12, 12, + 12, 12, 12, 12, 0, 0, 0, 0, 0, 16, + 12, 12, 12, 12, 12, 12, 9, 17, 9, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 0, + 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, + 9, 10, 16, 10, 0, 0, 10, 10, 10, 10, + 10, 10, 10, 10, 41, 0, 0, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, + 0, 0, 8, 42, 8, 34, 0, 8, 8, 8, + 8, 8, 8, 8, 8, 0, 40, 41, 0, 0, + 0, 8, 8, 8, 8, 8, 8, 43, 137, 138, + 139, 140, 141, 142, 42, 0, 0, 0, 0, 11, + 0, 11, 0, 0, 11, 11, 11, 11, 11, 11, + 11, 11, 17, 0, 0, 0, 0, 0, 11, 11, + 11, 11, 11, 11, 0, 7, 0, 7, 0, 0, + 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, + 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, + 0, 15, 0, 15, 0, 0, 15, 15, 15, 15, + 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 0, 13, 0, 13, + 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, + 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, + 13, 13, 0, 14, 0, 14, 0, 0, 14, 14, + 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, + 0, 0, 14, 14, 14, 14, 14, 14, 0, 0, + 1, 0, 2, 0, 0, 3, 4, 5, 6, 7, + 8, 9, 10, 0, 0, 0, 0, 0, 0, 11, + 12, 13, 14, 15, 16, 16, 0, 16, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 41, 41, + 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, + 41, 41, 41, 41, 41, 41, 41, 42, 42, 0, + 29, 0, 30, 31, 0, 32, 0, 0, 0, 42, + 42, 42, 42, 42, 42, 42, 0, 33, 0, 0, + 0, 43, 43, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 43, 43, 43, 43, 43, 43, 43, + 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, + 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 11, +}; +#if defined(__cplusplus) || defined(__STDC__) +const short yycheck[] = +#else +short yycheck[] = +#endif + { 33, + 0, 7, 76, 33, 33, 33, 43, 33, 45, 276, + 44, 33, 8, 9, 258, 44, 257, 258, 44, 282, + 283, 44, 44, 33, 61, 0, 258, 44, 260, 261, + 33, 263, 258, 33, 275, 261, 262, 263, 61, 258, + 258, 58, 258, 275, 44, 263, 258, 44, 259, 275, + 36, 0, 38, 39, 61, 129, 58, 275, 33, 263, + 46, 263, 61, 58, 263, 58, 40, 61, 58, 61, + 58, 44, 78, 44, 44, 44, 41, 0, 61, 61, + 283, 282, 44, 58, 33, 263, 82, 263, 84, 0, + 0, 41, 111, 41, 41, 80, 34, 69, 43, 60, + 17, 133, 120, 0, 71, 116, 115, 103, 124, 58, + 33, 88, -1, 22, -1, 79, -1, 85, 81, -1, + -1, -1, -1, 83, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, -1, 58, 33, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, + -1, 58, 33, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, -1, -1, -1, 58, 33, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 58, -1, + -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, + -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 259, -1, 257, 258, 258, + 258, 260, 261, 259, 263, 263, 0, 259, 33, 269, + 270, 271, 272, 273, 274, 275, 275, 275, -1, 259, + -1, -1, 282, 283, 257, 258, 256, -1, 258, -1, + -1, 261, 262, 263, 264, 265, 266, 267, 268, 33, + -1, -1, 275, 0, -1, 275, 276, 277, 278, 279, + 280, 256, 33, 258, -1, -1, 261, 262, 263, 264, + 265, 266, 267, 268, -1, -1, -1, -1, -1, 0, + 275, 276, 277, 278, 279, 280, 33, 256, -1, 258, + -1, -1, 261, 262, 263, 264, 265, 266, 267, 268, + -1, -1, -1, -1, -1, 0, 275, 276, 277, 278, + 279, 280, 33, 256, -1, 258, -1, -1, 261, 262, + 263, 264, 265, 266, 267, 268, -1, -1, -1, -1, + -1, 0, 275, 276, 277, 278, 279, 280, 33, 256, + -1, 258, -1, -1, 261, 262, 263, 264, 265, 266, + 267, 268, -1, -1, -1, -1, -1, 0, 275, 276, + 277, 278, 279, 280, 33, 256, -1, 258, -1, -1, + 261, 262, 263, 264, 265, 266, 267, 268, 258, -1, + -1, 261, 262, 263, 275, 276, 277, 278, 279, 280, + 33, 256, -1, 258, -1, 275, 261, 262, 263, 264, + 265, 266, 267, 268, -1, -1, -1, -1, -1, 0, + 275, 276, 277, 278, 279, 280, 256, 33, 258, -1, + -1, 261, 262, 263, 264, 265, 266, 267, 268, -1, + -1, -1, -1, -1, -1, 275, 276, 277, 278, 279, + 280, 256, 33, 258, -1, -1, 261, 262, 263, 264, + 265, 266, 267, 268, 33, -1, -1, -1, -1, -1, + 275, 276, 277, 278, 279, 280, -1, -1, -1, -1, + -1, -1, 256, 33, 258, 33, -1, 261, 262, 263, + 264, 265, 266, 267, 268, -1, 257, 258, -1, -1, + -1, 275, 276, 277, 278, 279, 280, 33, 269, 270, + 271, 272, 273, 274, 275, -1, -1, -1, -1, 256, + -1, 258, -1, -1, 261, 262, 263, 264, 265, 266, + 267, 268, 33, -1, -1, -1, -1, -1, 275, 276, + 277, 278, 279, 280, -1, 256, -1, 258, -1, -1, + 261, 262, 263, 264, 265, 266, 267, 268, -1, -1, + -1, -1, -1, -1, 275, 276, 277, 278, 279, 280, + -1, 256, -1, 258, -1, -1, 261, 262, 263, 264, + 265, 266, 267, 268, -1, -1, -1, -1, -1, -1, + 275, 276, 277, 278, 279, 280, -1, 256, -1, 258, + -1, -1, 261, 262, 263, 264, 265, 266, 267, 268, + -1, -1, -1, -1, -1, -1, 275, 276, 277, 278, + 279, 280, -1, 256, -1, 258, -1, -1, 261, 262, + 263, 264, 265, 266, 267, 268, -1, -1, -1, -1, + -1, -1, 275, 276, 277, 278, 279, 280, -1, -1, + 256, -1, 258, -1, -1, 261, 262, 263, 264, 265, + 266, 267, 268, -1, -1, -1, -1, -1, -1, 275, + 276, 277, 278, 279, 280, 256, -1, 258, -1, -1, + 261, 262, 263, 264, 265, 266, 267, 268, 257, 258, + -1, -1, -1, -1, 275, 276, 277, 278, 279, 280, + 269, 270, 271, 272, 273, 274, 275, 257, 258, -1, + 258, -1, 260, 261, -1, 263, -1, -1, -1, 269, + 270, 271, 272, 273, 274, 275, -1, 275, -1, -1, + -1, 257, 258, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 269, 270, 271, 272, 273, 274, 275, + -1, -1, -1, -1, -1, -1, -1, 258, -1, -1, + 261, 262, 263, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 275, +}; +#define YYFINAL 18 +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#define YYMAXTOKEN 283 +#if YYDEBUG +#if defined(__cplusplus) || defined(__STDC__) +const char * const yyname[] = +#else +char *yyname[] = +#endif + { +"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +"'!'",0,0,0,0,0,0,"'('","')'",0,"'+'","','","'-'",0,0,0,0,0,0,0,0,0,0,0,0,"':'", +0,0,"'='",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +"COMMAND","ALIAS","DEFVAR","NTWKADDR","NETGROUP","USERGROUP","WORD","DEFAULTS", +"DEFAULTS_HOST","DEFAULTS_USER","DEFAULTS_RUNAS","DEFAULTS_CMND","NOPASSWD", +"PASSWD","NOEXEC","EXEC","SETENV","NOSETENV","ALL","COMMENT","HOSTALIAS", +"CMNDALIAS","USERALIAS","RUNASALIAS","ERROR","TYPE","ROLE", +}; +#if defined(__cplusplus) || defined(__STDC__) +const char * const yyrule[] = +#else +char *yyrule[] = +#endif + {"$accept : file", +"file :", +"file : line", +"line : entry", +"line : line entry", +"entry : COMMENT", +"entry : error COMMENT", +"entry : userlist privileges", +"entry : USERALIAS useraliases", +"entry : HOSTALIAS hostaliases", +"entry : CMNDALIAS cmndaliases", +"entry : RUNASALIAS runasaliases", +"entry : DEFAULTS defaults_list", +"entry : DEFAULTS_USER userlist defaults_list", +"entry : DEFAULTS_RUNAS userlist defaults_list", +"entry : DEFAULTS_HOST hostlist defaults_list", +"entry : DEFAULTS_CMND cmndlist defaults_list", +"defaults_list : defaults_entry", +"defaults_list : defaults_list ',' defaults_entry", +"defaults_entry : DEFVAR", +"defaults_entry : '!' DEFVAR", +"defaults_entry : DEFVAR '=' WORD", +"defaults_entry : DEFVAR '+' WORD", +"defaults_entry : DEFVAR '-' WORD", +"privileges : privilege", +"privileges : privileges ':' privilege", +"privilege : hostlist '=' cmndspeclist", +"ophost : host", +"ophost : '!' host", +"host : ALIAS", +"host : ALL", +"host : NETGROUP", +"host : NTWKADDR", +"host : WORD", +"cmndspeclist : cmndspec", +"cmndspeclist : cmndspeclist ',' cmndspec", +"cmndspec : runasspec selinux cmndtag opcmnd", +"opcmnd : cmnd", +"opcmnd : '!' cmnd", +"rolespec : ROLE '=' WORD", +"typespec : TYPE '=' WORD", +"selinux :", +"selinux : rolespec", +"selinux : typespec", +"selinux : rolespec typespec", +"selinux : typespec rolespec", +"runasspec :", +"runasspec : '(' runaslist ')'", +"runaslist : userlist", +"runaslist : userlist ':' grouplist", +"runaslist : ':' grouplist", +"cmndtag :", +"cmndtag : cmndtag NOPASSWD", +"cmndtag : cmndtag PASSWD", +"cmndtag : cmndtag NOEXEC", +"cmndtag : cmndtag EXEC", +"cmndtag : cmndtag SETENV", +"cmndtag : cmndtag NOSETENV", +"cmnd : ALL", +"cmnd : ALIAS", +"cmnd : COMMAND", +"hostaliases : hostalias", +"hostaliases : hostaliases ':' hostalias", +"hostalias : ALIAS '=' hostlist", +"hostlist : ophost", +"hostlist : hostlist ',' ophost", +"cmndaliases : cmndalias", +"cmndaliases : cmndaliases ':' cmndalias", +"cmndalias : ALIAS '=' cmndlist", +"cmndlist : opcmnd", +"cmndlist : cmndlist ',' opcmnd", +"runasaliases : runasalias", +"runasaliases : runasaliases ':' runasalias", +"runasalias : ALIAS '=' userlist", +"useraliases : useralias", +"useraliases : useraliases ':' useralias", +"useralias : ALIAS '=' userlist", +"userlist : opuser", +"userlist : userlist ',' opuser", +"opuser : user", +"opuser : '!' user", +"user : ALIAS", +"user : ALL", +"user : NETGROUP", +"user : USERGROUP", +"user : WORD", +"grouplist : opgroup", +"grouplist : grouplist ',' opgroup", +"opgroup : group", +"opgroup : '!' group", +"group : ALIAS", +"group : ALL", +"group : WORD", +}; +#endif +#ifdef YYSTACKSIZE +#undef YYMAXDEPTH +#define YYMAXDEPTH YYSTACKSIZE +#else +#ifdef YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#else +#define YYSTACKSIZE 10000 +#define YYMAXDEPTH 10000 +#endif +#endif +#define YYINITSTACKSIZE 200 +/* LINTUSED */ +int yydebug; +int yynerrs; +int yyerrflag; +int yychar; +short *yyssp; +YYSTYPE *yyvsp; +YYSTYPE yyval; +YYSTYPE yylval; +short *yyss; +short *yysslim; +YYSTYPE *yyvs; +int yystacksize; +#line 590 "gram.y" +static struct defaults * +new_default(var, val, op) + char *var; + char *val; + int op; +{ + struct defaults *d; + + d = emalloc(sizeof(struct defaults)); + d->var = var; + d->val = val; + tq_init(&d->binding); + d->type = 0; + d->op = op; + d->prev = d; + d->next = NULL; + + return(d); +} + +static struct member * +new_member(name, type) + char *name; + int type; +{ + struct member *m; + + m = emalloc(sizeof(struct member)); + m->name = name; + m->type = type; + m->prev = m; + m->next = NULL; + + return(m); +} + +/* + * Add a list of defaults structures to the defaults list. + * The binding, if non-NULL, specifies a list of hosts, users, or + * runas users the entries apply to (specified by the type). + */ +static void +add_defaults(type, bmem, defs) + int type; + struct member *bmem; + struct defaults *defs; +{ + struct defaults *d; + struct member_list binding; + + /* + * We can only call list2tq once on bmem as it will zero + * out the prev pointer when it consumes bmem. + */ + list2tq(&binding, bmem); + + /* + * Set type and binding (who it applies to) for new entries. + */ + for (d = defs; d != NULL; d = d->next) { + d->type = type; + d->binding = binding; + } + tq_append(&defaults, defs); +} + +/* + * Allocate a new struct userspec, populate it, and insert it at the + * and of the userspecs list. + */ +static void +add_userspec(members, privs) + struct member *members; + struct privilege *privs; +{ + struct userspec *u; + + u = emalloc(sizeof(*u)); + list2tq(&u->users, members); + list2tq(&u->privileges, privs); + u->prev = u; + u->next = NULL; + tq_append(&userspecs, u); +} + +/* + * Free up space used by data structures from a previous parser run and sets + * the current sudoers file to path. + */ +void +init_parser(path, quiet) + char *path; + int quiet; +{ + struct defaults *d; + struct member *m, *binding; + struct userspec *us; + struct privilege *priv; + struct cmndspec *cs; + struct sudo_command *c; + + while ((us = tq_pop(&userspecs)) != NULL) { + while ((m = tq_pop(&us->users)) != NULL) { + efree(m->name); + efree(m); + } + while ((priv = tq_pop(&us->privileges)) != NULL) { + struct member *runasuser = NULL, *runasgroup = NULL; +#ifdef HAVE_SELINUX + char *role = NULL, *type = NULL; +#endif /* HAVE_SELINUX */ + + while ((m = tq_pop(&priv->hostlist)) != NULL) { + efree(m->name); + efree(m); + } + while ((cs = tq_pop(&priv->cmndlist)) != NULL) { +#ifdef HAVE_SELINUX + /* Only free the first instance of a role/type. */ + if (cs->role != role) { + role = cs->role; + efree(cs->role); + } + if (cs->type != type) { + type = cs->type; + efree(cs->type); + } +#endif /* HAVE_SELINUX */ + if (tq_last(&cs->runasuserlist) != runasuser) { + runasuser = tq_last(&cs->runasuserlist); + while ((m = tq_pop(&cs->runasuserlist)) != NULL) { + efree(m->name); + efree(m); + } + } + if (tq_last(&cs->runasgrouplist) != runasgroup) { + runasgroup = tq_last(&cs->runasgrouplist); + while ((m = tq_pop(&cs->runasgrouplist)) != NULL) { + efree(m->name); + efree(m); + } + } + if (cs->cmnd->type == COMMAND) { + c = (struct sudo_command *) cs->cmnd->name; + efree(c->cmnd); + efree(c->args); + } + efree(cs->cmnd->name); + efree(cs->cmnd); + efree(cs); + } + efree(priv); + } + efree(us); + } + tq_init(&userspecs); + + binding = NULL; + while ((d = tq_pop(&defaults)) != NULL) { + if (tq_last(&d->binding) != binding) { + binding = tq_last(&d->binding); + while ((m = tq_pop(&d->binding)) != NULL) { + if (m->type == COMMAND) { + c = (struct sudo_command *) m->name; + efree(c->cmnd); + efree(c->args); + } + efree(m->name); + efree(m); + } + } + efree(d->var); + efree(d->val); + efree(d); + } + tq_init(&defaults); + + init_aliases(); + + efree(sudoers); + sudoers = path ? estrdup(path) : NULL; + + parse_error = FALSE; + errorlineno = -1; + sudolineno = 1; + verbose = !quiet; +} +#line 758 "y.tab.c" +/* allocate initial stack or double stack size, up to YYMAXDEPTH */ +#if defined(__cplusplus) || defined(__STDC__) +static int yygrowstack(void) +#else +static int yygrowstack() +#endif +{ + int newsize, i; + short *newss; + YYSTYPE *newvs; + + if ((newsize = yystacksize) == 0) + newsize = YYINITSTACKSIZE; + else if (newsize >= YYMAXDEPTH) + return -1; + else if ((newsize *= 2) > YYMAXDEPTH) + newsize = YYMAXDEPTH; + i = yyssp - yyss; +#ifdef SIZE_MAX +#define YY_SIZE_MAX SIZE_MAX +#else +#define YY_SIZE_MAX 0x7fffffff +#endif + if (newsize && YY_SIZE_MAX / newsize < sizeof *newss) + goto bail; + newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) : + (short *)malloc(newsize * sizeof *newss); /* overflow check above */ + if (newss == NULL) + goto bail; + yyss = newss; + yyssp = newss + i; + if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs) + goto bail; + newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) : + (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */ + if (newvs == NULL) + goto bail; + yyvs = newvs; + yyvsp = newvs + i; + yystacksize = newsize; + yysslim = yyss + newsize - 1; + return 0; +bail: + if (yyss) + free(yyss); + if (yyvs) + free(yyvs); + yyss = yyssp = NULL; + yyvs = yyvsp = NULL; + yystacksize = 0; + return -1; +} + +#define YYABORT goto yyabort +#define YYREJECT goto yyabort +#define YYACCEPT goto yyaccept +#define YYERROR goto yyerrlab +int +#if defined(__cplusplus) || defined(__STDC__) +yyparse(void) +#else +yyparse() +#endif +{ + int yym, yyn, yystate; +#if YYDEBUG +#if defined(__cplusplus) || defined(__STDC__) + const char *yys; +#else /* !(defined(__cplusplus) || defined(__STDC__)) */ + char *yys; +#endif /* !(defined(__cplusplus) || defined(__STDC__)) */ + + if ((yys = getenv("YYDEBUG"))) + { + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } +#endif /* YYDEBUG */ + + yynerrs = 0; + yyerrflag = 0; + yychar = (-1); + + if (yyss == NULL && yygrowstack()) goto yyoverflow; + yyssp = yyss; + yyvsp = yyvs; + *yyssp = yystate = 0; + +yyloop: + if ((yyn = yydefred[yystate]) != 0) goto yyreduce; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, yystate, yychar, yys); + } +#endif + } + if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, shifting to state %d\n", + YYPREFIX, yystate, yytable[yyn]); +#endif + if (yyssp >= yysslim && yygrowstack()) + { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + yychar = (-1); + if (yyerrflag > 0) --yyerrflag; + goto yyloop; + } + if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { + yyn = yytable[yyn]; + goto yyreduce; + } + if (yyerrflag) goto yyinrecovery; +#if defined(lint) || defined(__GNUC__) + goto yynewerror; +#endif +yynewerror: + yyerror("syntax error"); +#if defined(lint) || defined(__GNUC__) + goto yyerrlab; +#endif +yyerrlab: + ++yynerrs; +yyinrecovery: + if (yyerrflag < 3) + { + yyerrflag = 3; + for (;;) + { + if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, error recovery shifting\ + to state %d\n", YYPREFIX, *yyssp, yytable[yyn]); +#endif + if (yyssp >= yysslim && yygrowstack()) + { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + goto yyloop; + } + else + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: error recovery discarding state %d\n", + YYPREFIX, *yyssp); +#endif + if (yyssp <= yyss) goto yyabort; + --yyssp; + --yyvsp; + } + } + } + else + { + if (yychar == 0) goto yyabort; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, error recovery discards token %d (%s)\n", + YYPREFIX, yystate, yychar, yys); + } +#endif + yychar = (-1); + goto yyloop; + } +yyreduce: +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, reducing by rule %d (%s)\n", + YYPREFIX, yystate, yyn, yyrule[yyn]); +#endif + yym = yylen[yyn]; + if (yym) + yyval = yyvsp[1-yym]; + else + memset(&yyval, 0, sizeof yyval); + switch (yyn) + { +case 1: +#line 188 "gram.y" +{ ; } +break; +case 5: +#line 196 "gram.y" +{ + ; + } +break; +case 6: +#line 199 "gram.y" +{ + yyerrok; + } +break; +case 7: +#line 202 "gram.y" +{ + add_userspec(yyvsp[-1].member, yyvsp[0].privilege); + } +break; +case 8: +#line 205 "gram.y" +{ + ; + } +break; +case 9: +#line 208 "gram.y" +{ + ; + } +break; +case 10: +#line 211 "gram.y" +{ + ; + } +break; +case 11: +#line 214 "gram.y" +{ + ; + } +break; +case 12: +#line 217 "gram.y" +{ + add_defaults(DEFAULTS, NULL, yyvsp[0].defaults); + } +break; +case 13: +#line 220 "gram.y" +{ + add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults); + } +break; +case 14: +#line 223 "gram.y" +{ + add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults); + } +break; +case 15: +#line 226 "gram.y" +{ + add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults); + } +break; +case 16: +#line 229 "gram.y" +{ + add_defaults(DEFAULTS_CMND, yyvsp[-1].member, yyvsp[0].defaults); + } +break; +case 18: +#line 235 "gram.y" +{ + list_append(yyvsp[-2].defaults, yyvsp[0].defaults); + yyval.defaults = yyvsp[-2].defaults; + } +break; +case 19: +#line 241 "gram.y" +{ + yyval.defaults = new_default(yyvsp[0].string, NULL, TRUE); + } +break; +case 20: +#line 244 "gram.y" +{ + yyval.defaults = new_default(yyvsp[0].string, NULL, FALSE); + } +break; +case 21: +#line 247 "gram.y" +{ + yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, TRUE); + } +break; +case 22: +#line 250 "gram.y" +{ + yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '+'); + } +break; +case 23: +#line 253 "gram.y" +{ + yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '-'); + } +break; +case 25: +#line 259 "gram.y" +{ + list_append(yyvsp[-2].privilege, yyvsp[0].privilege); + yyval.privilege = yyvsp[-2].privilege; + } +break; +case 26: +#line 265 "gram.y" +{ + struct privilege *p = emalloc(sizeof(*p)); + list2tq(&p->hostlist, yyvsp[-2].member); + list2tq(&p->cmndlist, yyvsp[0].cmndspec); + p->prev = p; + p->next = NULL; + yyval.privilege = p; + } +break; +case 27: +#line 275 "gram.y" +{ + yyval.member = yyvsp[0].member; + yyval.member->negated = FALSE; + } +break; +case 28: +#line 279 "gram.y" +{ + yyval.member = yyvsp[0].member; + yyval.member->negated = TRUE; + } +break; +case 29: +#line 285 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, ALIAS); + } +break; +case 30: +#line 288 "gram.y" +{ + yyval.member = new_member(NULL, ALL); + } +break; +case 31: +#line 291 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, NETGROUP); + } +break; +case 32: +#line 294 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, NTWKADDR); + } +break; +case 33: +#line 297 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, WORD); + } +break; +case 35: +#line 303 "gram.y" +{ + list_append(yyvsp[-2].cmndspec, yyvsp[0].cmndspec); +#ifdef HAVE_SELINUX + /* propagate role and type */ + if (yyvsp[0].cmndspec->role == NULL) + yyvsp[0].cmndspec->role = yyvsp[0].cmndspec->prev->role; + if (yyvsp[0].cmndspec->type == NULL) + yyvsp[0].cmndspec->type = yyvsp[0].cmndspec->prev->type; +#endif /* HAVE_SELINUX */ + /* propagate tags and runas list */ + if (yyvsp[0].cmndspec->tags.nopasswd == UNSPEC) + yyvsp[0].cmndspec->tags.nopasswd = yyvsp[0].cmndspec->prev->tags.nopasswd; + if (yyvsp[0].cmndspec->tags.noexec == UNSPEC) + yyvsp[0].cmndspec->tags.noexec = yyvsp[0].cmndspec->prev->tags.noexec; + if (yyvsp[0].cmndspec->tags.setenv == UNSPEC && + yyvsp[0].cmndspec->prev->tags.setenv != IMPLIED) + yyvsp[0].cmndspec->tags.setenv = yyvsp[0].cmndspec->prev->tags.setenv; + if ((tq_empty(&yyvsp[0].cmndspec->runasuserlist) && + tq_empty(&yyvsp[0].cmndspec->runasgrouplist)) && + (!tq_empty(&yyvsp[0].cmndspec->prev->runasuserlist) || + !tq_empty(&yyvsp[0].cmndspec->prev->runasgrouplist))) { + yyvsp[0].cmndspec->runasuserlist = yyvsp[0].cmndspec->prev->runasuserlist; + yyvsp[0].cmndspec->runasgrouplist = yyvsp[0].cmndspec->prev->runasgrouplist; + } + yyval.cmndspec = yyvsp[-2].cmndspec; + } +break; +case 36: +#line 331 "gram.y" +{ + struct cmndspec *cs = emalloc(sizeof(*cs)); + if (yyvsp[-3].runas != NULL) { + list2tq(&cs->runasuserlist, yyvsp[-3].runas->runasusers); + list2tq(&cs->runasgrouplist, yyvsp[-3].runas->runasgroups); + efree(yyvsp[-3].runas); + } else { + tq_init(&cs->runasuserlist); + tq_init(&cs->runasgrouplist); + } +#ifdef HAVE_SELINUX + cs->role = yyvsp[-2].seinfo.role; + cs->type = yyvsp[-2].seinfo.type; +#endif + cs->tags = yyvsp[-1].tag; + cs->cmnd = yyvsp[0].member; + cs->prev = cs; + cs->next = NULL; + /* sudo "ALL" implies the SETENV tag */ + if (cs->cmnd->type == ALL && !cs->cmnd->negated && + cs->tags.setenv == UNSPEC) + cs->tags.setenv = IMPLIED; + yyval.cmndspec = cs; + } +break; +case 37: +#line 357 "gram.y" +{ + yyval.member = yyvsp[0].member; + yyval.member->negated = FALSE; + } +break; +case 38: +#line 361 "gram.y" +{ + yyval.member = yyvsp[0].member; + yyval.member->negated = TRUE; + } +break; +case 39: +#line 367 "gram.y" +{ + yyval.string = yyvsp[0].string; + } +break; +case 40: +#line 372 "gram.y" +{ + yyval.string = yyvsp[0].string; + } +break; +case 41: +#line 377 "gram.y" +{ + yyval.seinfo.role = NULL; + yyval.seinfo.type = NULL; + } +break; +case 42: +#line 381 "gram.y" +{ + yyval.seinfo.role = yyvsp[0].string; + yyval.seinfo.type = NULL; + } +break; +case 43: +#line 385 "gram.y" +{ + yyval.seinfo.type = yyvsp[0].string; + yyval.seinfo.role = NULL; + } +break; +case 44: +#line 389 "gram.y" +{ + yyval.seinfo.role = yyvsp[-1].string; + yyval.seinfo.type = yyvsp[0].string; + } +break; +case 45: +#line 393 "gram.y" +{ + yyval.seinfo.type = yyvsp[-1].string; + yyval.seinfo.role = yyvsp[0].string; + } +break; +case 46: +#line 399 "gram.y" +{ + yyval.runas = NULL; + } +break; +case 47: +#line 402 "gram.y" +{ + yyval.runas = yyvsp[-1].runas; + } +break; +case 48: +#line 407 "gram.y" +{ + yyval.runas = emalloc(sizeof(struct runascontainer)); + yyval.runas->runasusers = yyvsp[0].member; + yyval.runas->runasgroups = NULL; + } +break; +case 49: +#line 412 "gram.y" +{ + yyval.runas = emalloc(sizeof(struct runascontainer)); + yyval.runas->runasusers = yyvsp[-2].member; + yyval.runas->runasgroups = yyvsp[0].member; + } +break; +case 50: +#line 417 "gram.y" +{ + yyval.runas = emalloc(sizeof(struct runascontainer)); + yyval.runas->runasusers = NULL; + yyval.runas->runasgroups = yyvsp[0].member; + } +break; +case 51: +#line 424 "gram.y" +{ + yyval.tag.nopasswd = yyval.tag.noexec = yyval.tag.setenv = UNSPEC; + } +break; +case 52: +#line 427 "gram.y" +{ + yyval.tag.nopasswd = TRUE; + } +break; +case 53: +#line 430 "gram.y" +{ + yyval.tag.nopasswd = FALSE; + } +break; +case 54: +#line 433 "gram.y" +{ + yyval.tag.noexec = TRUE; + } +break; +case 55: +#line 436 "gram.y" +{ + yyval.tag.noexec = FALSE; + } +break; +case 56: +#line 439 "gram.y" +{ + yyval.tag.setenv = TRUE; + } +break; +case 57: +#line 442 "gram.y" +{ + yyval.tag.setenv = FALSE; + } +break; +case 58: +#line 447 "gram.y" +{ + yyval.member = new_member(NULL, ALL); + } +break; +case 59: +#line 450 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, ALIAS); + } +break; +case 60: +#line 453 "gram.y" +{ + struct sudo_command *c = emalloc(sizeof(*c)); + c->cmnd = yyvsp[0].command.cmnd; + c->args = yyvsp[0].command.args; + yyval.member = new_member((char *)c, COMMAND); + } +break; +case 63: +#line 465 "gram.y" +{ + char *s; + if ((s = alias_add(yyvsp[-2].string, HOSTALIAS, yyvsp[0].member)) != NULL) { + yyerror(s); + YYERROR; + } + } +break; +case 65: +#line 475 "gram.y" +{ + list_append(yyvsp[-2].member, yyvsp[0].member); + yyval.member = yyvsp[-2].member; + } +break; +case 68: +#line 485 "gram.y" +{ + char *s; + if ((s = alias_add(yyvsp[-2].string, CMNDALIAS, yyvsp[0].member)) != NULL) { + yyerror(s); + YYERROR; + } + } +break; +case 70: +#line 495 "gram.y" +{ + list_append(yyvsp[-2].member, yyvsp[0].member); + yyval.member = yyvsp[-2].member; + } +break; +case 73: +#line 505 "gram.y" +{ + char *s; + if ((s = alias_add(yyvsp[-2].string, RUNASALIAS, yyvsp[0].member)) != NULL) { + yyerror(s); + YYERROR; + } + } +break; +case 76: +#line 518 "gram.y" +{ + char *s; + if ((s = alias_add(yyvsp[-2].string, USERALIAS, yyvsp[0].member)) != NULL) { + yyerror(s); + YYERROR; + } + } +break; +case 78: +#line 528 "gram.y" +{ + list_append(yyvsp[-2].member, yyvsp[0].member); + yyval.member = yyvsp[-2].member; + } +break; +case 79: +#line 534 "gram.y" +{ + yyval.member = yyvsp[0].member; + yyval.member->negated = FALSE; + } +break; +case 80: +#line 538 "gram.y" +{ + yyval.member = yyvsp[0].member; + yyval.member->negated = TRUE; + } +break; +case 81: +#line 544 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, ALIAS); + } +break; +case 82: +#line 547 "gram.y" +{ + yyval.member = new_member(NULL, ALL); + } +break; +case 83: +#line 550 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, NETGROUP); + } +break; +case 84: +#line 553 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, USERGROUP); + } +break; +case 85: +#line 556 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, WORD); + } +break; +case 87: +#line 562 "gram.y" +{ + list_append(yyvsp[-2].member, yyvsp[0].member); + yyval.member = yyvsp[-2].member; + } +break; +case 88: +#line 568 "gram.y" +{ + yyval.member = yyvsp[0].member; + yyval.member->negated = FALSE; + } +break; +case 89: +#line 572 "gram.y" +{ + yyval.member = yyvsp[0].member; + yyval.member->negated = TRUE; + } +break; +case 90: +#line 578 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, ALIAS); + } +break; +case 91: +#line 581 "gram.y" +{ + yyval.member = new_member(NULL, ALL); + } +break; +case 92: +#line 584 "gram.y" +{ + yyval.member = new_member(yyvsp[0].string, WORD); + } +break; +#line 1498 "y.tab.c" + } + yyssp -= yym; + yystate = *yyssp; + yyvsp -= yym; + yym = yylhs[yyn]; + if (yystate == 0 && yym == 0) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state 0 to\ + state %d\n", YYPREFIX, YYFINAL); +#endif + yystate = YYFINAL; + *++yyssp = YYFINAL; + *++yyvsp = yyval; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, YYFINAL, yychar, yys); + } +#endif + } + if (yychar == 0) goto yyaccept; + goto yyloop; + } + if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yystate) + yystate = yytable[yyn]; + else + yystate = yydgoto[yym]; +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state %d \ +to state %d\n", YYPREFIX, *yyssp, yystate); +#endif + if (yyssp >= yysslim && yygrowstack()) + { + goto yyoverflow; + } + *++yyssp = yystate; + *++yyvsp = yyval; + goto yyloop; +yyoverflow: + yyerror("yacc stack overflow"); +yyabort: + if (yyss) + free(yyss); + if (yyvs) + free(yyvs); + yyss = yyssp = NULL; + yyvs = yyvsp = NULL; + yystacksize = 0; + return (1); +yyaccept: + if (yyss) + free(yyss); + if (yyvs) + free(yyvs); + yyss = yyssp = NULL; + yyvs = yyvsp = NULL; + yystacksize = 0; + return (0); +} diff --git a/gram.h b/gram.h new file mode 100644 index 0000000..8f05491 --- /dev/null +++ b/gram.h @@ -0,0 +1,43 @@ +#define COMMAND 257 +#define ALIAS 258 +#define DEFVAR 259 +#define NTWKADDR 260 +#define NETGROUP 261 +#define USERGROUP 262 +#define WORD 263 +#define DEFAULTS 264 +#define DEFAULTS_HOST 265 +#define DEFAULTS_USER 266 +#define DEFAULTS_RUNAS 267 +#define DEFAULTS_CMND 268 +#define NOPASSWD 269 +#define PASSWD 270 +#define NOEXEC 271 +#define EXEC 272 +#define SETENV 273 +#define NOSETENV 274 +#define ALL 275 +#define COMMENT 276 +#define HOSTALIAS 277 +#define CMNDALIAS 278 +#define USERALIAS 279 +#define RUNASALIAS 280 +#define ERROR 281 +#define TYPE 282 +#define ROLE 283 +#ifndef YYSTYPE_DEFINED +#define YYSTYPE_DEFINED +typedef union { + struct cmndspec *cmndspec; + struct defaults *defaults; + struct member *member; + struct runascontainer *runas; + struct privilege *privilege; + struct sudo_command command; + struct cmndtag tag; + struct selinux_info seinfo; + char *string; + int tok; +} YYSTYPE; +#endif /* YYSTYPE_DEFINED */ +extern YYSTYPE yylval; diff --git a/gram.y b/gram.y new file mode 100644 index 0000000..d39068d --- /dev/null +++ b/gram.y @@ -0,0 +1,776 @@ +%{ +/* + * Copyright (c) 1996, 1998-2005, 2007-2008 + * 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. + * + * 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. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__) +# include +#endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */ +#include + +#include "sudo.h" +#include "parse.h" + +#ifndef lint +__unused static const char rcsid[] = "$Sudo: gram.y,v 1.34 2008/11/09 14:13:12 millert Exp $"; +#endif /* lint */ + +/* + * We must define SIZE_MAX for yacc's skeleton.c. + * If there is no SIZE_MAX or SIZE_T_MAX we have to assume that size_t + * could be signed (as it is on SunOS 4.x). + */ +#ifndef SIZE_MAX +# ifdef SIZE_T_MAX +# define SIZE_MAX SIZE_T_MAX +# else +# define SIZE_MAX INT_MAX +# endif /* SIZE_T_MAX */ +#endif /* SIZE_MAX */ + +/* + * Globals + */ +extern int sudolineno; +extern char *sudoers; +int parse_error; +int pedantic = FALSE; +int verbose = FALSE; +int errorlineno = -1; +char *errorfile = NULL; + +struct defaults_list defaults; +struct userspec_list userspecs; + +/* + * Local protoypes + */ +static void add_defaults __P((int, struct member *, struct defaults *)); +static void add_userspec __P((struct member *, struct privilege *)); +static struct defaults *new_default __P((char *, char *, int)); +static struct member *new_member __P((char *, int)); + void yyerror __P((const char *)); + +void +yyerror(s) + const char *s; +{ + /* Save the line the first error occurred on. */ + if (errorlineno == -1) { + errorlineno = sudolineno ? sudolineno - 1 : 0; + errorfile = estrdup(sudoers); + } + if (verbose && s != NULL) { +#ifndef TRACELEXER + (void) fprintf(stderr, ">>> %s: %s near line %d <<<\n", sudoers, s, + sudolineno ? sudolineno - 1 : 0); +#else + (void) fprintf(stderr, "<*> "); +#endif + } + parse_error = TRUE; +} +%} + +%union { + struct cmndspec *cmndspec; + struct defaults *defaults; + struct member *member; + struct runascontainer *runas; + struct privilege *privilege; + struct sudo_command command; + struct cmndtag tag; + struct selinux_info seinfo; + char *string; + int tok; +} + +%start file /* special start symbol */ +%token COMMAND /* absolute pathname w/ optional args */ +%token ALIAS /* an UPPERCASE alias name */ +%token DEFVAR /* a Defaults variable name */ +%token NTWKADDR /* ipv4 or ipv6 address */ +%token NETGROUP /* a netgroup (+NAME) */ +%token USERGROUP /* a usergroup (%NAME) */ +%token WORD /* a word */ +%token DEFAULTS /* Defaults entry */ +%token DEFAULTS_HOST /* Host-specific defaults entry */ +%token DEFAULTS_USER /* User-specific defaults entry */ +%token DEFAULTS_RUNAS /* Runas-specific defaults entry */ +%token DEFAULTS_CMND /* Command-specific defaults entry */ +%token NOPASSWD /* no passwd req for command */ +%token PASSWD /* passwd req for command (default) */ +%token NOEXEC /* preload dummy execve() for cmnd */ +%token EXEC /* don't preload dummy execve() */ +%token SETENV /* user may set environment for cmnd */ +%token NOSETENV /* user may not set environment */ +%token ALL /* ALL keyword */ +%token COMMENT /* comment and/or carriage return */ +%token HOSTALIAS /* Host_Alias keyword */ +%token CMNDALIAS /* Cmnd_Alias keyword */ +%token USERALIAS /* User_Alias keyword */ +%token RUNASALIAS /* Runas_Alias keyword */ +%token ':' '=' ',' '!' '+' '-' /* union member tokens */ +%token '(' ')' /* runas tokens */ +%token ERROR +%token TYPE /* SELinux type */ +%token ROLE /* SELinux role */ + +%type cmndspec +%type cmndspeclist +%type defaults_entry +%type defaults_list +%type cmnd +%type opcmnd +%type cmndlist +%type host +%type hostlist +%type ophost +%type opuser +%type user +%type userlist +%type opgroup +%type group +%type grouplist +%type runasspec +%type runaslist +%type privilege +%type privileges +%type cmndtag +%type selinux +%type rolespec +%type typespec + +%% + +file : { ; } + | line + ; + +line : entry + | line entry + ; + +entry : COMMENT { + ; + } + | error COMMENT { + yyerrok; + } + | userlist privileges { + add_userspec($1, $2); + } + | USERALIAS useraliases { + ; + } + | HOSTALIAS hostaliases { + ; + } + | CMNDALIAS cmndaliases { + ; + } + | RUNASALIAS runasaliases { + ; + } + | DEFAULTS defaults_list { + add_defaults(DEFAULTS, NULL, $2); + } + | DEFAULTS_USER userlist defaults_list { + add_defaults(DEFAULTS_USER, $2, $3); + } + | DEFAULTS_RUNAS userlist defaults_list { + add_defaults(DEFAULTS_RUNAS, $2, $3); + } + | DEFAULTS_HOST hostlist defaults_list { + add_defaults(DEFAULTS_HOST, $2, $3); + } + | DEFAULTS_CMND cmndlist defaults_list { + add_defaults(DEFAULTS_CMND, $2, $3); + } + ; + +defaults_list : defaults_entry + | defaults_list ',' defaults_entry { + list_append($1, $3); + $$ = $1; + } + ; + +defaults_entry : DEFVAR { + $$ = new_default($1, NULL, TRUE); + } + | '!' DEFVAR { + $$ = new_default($2, NULL, FALSE); + } + | DEFVAR '=' WORD { + $$ = new_default($1, $3, TRUE); + } + | DEFVAR '+' WORD { + $$ = new_default($1, $3, '+'); + } + | DEFVAR '-' WORD { + $$ = new_default($1, $3, '-'); + } + ; + +privileges : privilege + | privileges ':' privilege { + list_append($1, $3); + $$ = $1; + } + ; + +privilege : hostlist '=' cmndspeclist { + struct privilege *p = emalloc(sizeof(*p)); + list2tq(&p->hostlist, $1); + list2tq(&p->cmndlist, $3); + p->prev = p; + p->next = NULL; + $$ = p; + } + ; + +ophost : host { + $$ = $1; + $$->negated = FALSE; + } + | '!' host { + $$ = $2; + $$->negated = TRUE; + } + ; + +host : ALIAS { + $$ = new_member($1, ALIAS); + } + | ALL { + $$ = new_member(NULL, ALL); + } + | NETGROUP { + $$ = new_member($1, NETGROUP); + } + | NTWKADDR { + $$ = new_member($1, NTWKADDR); + } + | WORD { + $$ = new_member($1, WORD); + } + ; + +cmndspeclist : cmndspec + | cmndspeclist ',' cmndspec { + list_append($1, $3); +#ifdef HAVE_SELINUX + /* propagate role and type */ + if ($3->role == NULL) + $3->role = $3->prev->role; + if ($3->type == NULL) + $3->type = $3->prev->type; +#endif /* HAVE_SELINUX */ + /* propagate tags and runas list */ + if ($3->tags.nopasswd == UNSPEC) + $3->tags.nopasswd = $3->prev->tags.nopasswd; + if ($3->tags.noexec == UNSPEC) + $3->tags.noexec = $3->prev->tags.noexec; + if ($3->tags.setenv == UNSPEC && + $3->prev->tags.setenv != IMPLIED) + $3->tags.setenv = $3->prev->tags.setenv; + if ((tq_empty(&$3->runasuserlist) && + tq_empty(&$3->runasgrouplist)) && + (!tq_empty(&$3->prev->runasuserlist) || + !tq_empty(&$3->prev->runasgrouplist))) { + $3->runasuserlist = $3->prev->runasuserlist; + $3->runasgrouplist = $3->prev->runasgrouplist; + } + $$ = $1; + } + ; + +cmndspec : runasspec selinux cmndtag opcmnd { + struct cmndspec *cs = emalloc(sizeof(*cs)); + if ($1 != NULL) { + list2tq(&cs->runasuserlist, $1->runasusers); + list2tq(&cs->runasgrouplist, $1->runasgroups); + efree($1); + } else { + tq_init(&cs->runasuserlist); + tq_init(&cs->runasgrouplist); + } +#ifdef HAVE_SELINUX + cs->role = $2.role; + cs->type = $2.type; +#endif + cs->tags = $3; + cs->cmnd = $4; + cs->prev = cs; + cs->next = NULL; + /* sudo "ALL" implies the SETENV tag */ + if (cs->cmnd->type == ALL && !cs->cmnd->negated && + cs->tags.setenv == UNSPEC) + cs->tags.setenv = IMPLIED; + $$ = cs; + } + ; + +opcmnd : cmnd { + $$ = $1; + $$->negated = FALSE; + } + | '!' cmnd { + $$ = $2; + $$->negated = TRUE; + } + ; + +rolespec : ROLE '=' WORD { + $$ = $3; + } + ; + +typespec : TYPE '=' WORD { + $$ = $3; + } + ; + +selinux : /* empty */ { + $$.role = NULL; + $$.type = NULL; + } + | rolespec { + $$.role = $1; + $$.type = NULL; + } + | typespec { + $$.type = $1; + $$.role = NULL; + } + | rolespec typespec { + $$.role = $1; + $$.type = $2; + } + | typespec rolespec { + $$.type = $1; + $$.role = $2; + } + ; + +runasspec : /* empty */ { + $$ = NULL; + } + | '(' runaslist ')' { + $$ = $2; + } + ; + +runaslist : userlist { + $$ = emalloc(sizeof(struct runascontainer)); + $$->runasusers = $1; + $$->runasgroups = NULL; + } + | userlist ':' grouplist { + $$ = emalloc(sizeof(struct runascontainer)); + $$->runasusers = $1; + $$->runasgroups = $3; + } + | ':' grouplist { + $$ = emalloc(sizeof(struct runascontainer)); + $$->runasusers = NULL; + $$->runasgroups = $2; + } + ; + +cmndtag : /* empty */ { + $$.nopasswd = $$.noexec = $$.setenv = UNSPEC; + } + | cmndtag NOPASSWD { + $$.nopasswd = TRUE; + } + | cmndtag PASSWD { + $$.nopasswd = FALSE; + } + | cmndtag NOEXEC { + $$.noexec = TRUE; + } + | cmndtag EXEC { + $$.noexec = FALSE; + } + | cmndtag SETENV { + $$.setenv = TRUE; + } + | cmndtag NOSETENV { + $$.setenv = FALSE; + } + ; + +cmnd : ALL { + $$ = new_member(NULL, ALL); + } + | ALIAS { + $$ = new_member($1, ALIAS); + } + | COMMAND { + struct sudo_command *c = emalloc(sizeof(*c)); + c->cmnd = $1.cmnd; + c->args = $1.args; + $$ = new_member((char *)c, COMMAND); + } + ; + +hostaliases : hostalias + | hostaliases ':' hostalias + ; + +hostalias : ALIAS '=' hostlist { + char *s; + if ((s = alias_add($1, HOSTALIAS, $3)) != NULL) { + yyerror(s); + YYERROR; + } + } + ; + +hostlist : ophost + | hostlist ',' ophost { + list_append($1, $3); + $$ = $1; + } + ; + +cmndaliases : cmndalias + | cmndaliases ':' cmndalias + ; + +cmndalias : ALIAS '=' cmndlist { + char *s; + if ((s = alias_add($1, CMNDALIAS, $3)) != NULL) { + yyerror(s); + YYERROR; + } + } + ; + +cmndlist : opcmnd + | cmndlist ',' opcmnd { + list_append($1, $3); + $$ = $1; + } + ; + +runasaliases : runasalias + | runasaliases ':' runasalias + ; + +runasalias : ALIAS '=' userlist { + char *s; + if ((s = alias_add($1, RUNASALIAS, $3)) != NULL) { + yyerror(s); + YYERROR; + } + } + ; + +useraliases : useralias + | useraliases ':' useralias + ; + +useralias : ALIAS '=' userlist { + char *s; + if ((s = alias_add($1, USERALIAS, $3)) != NULL) { + yyerror(s); + YYERROR; + } + } + ; + +userlist : opuser + | userlist ',' opuser { + list_append($1, $3); + $$ = $1; + } + ; + +opuser : user { + $$ = $1; + $$->negated = FALSE; + } + | '!' user { + $$ = $2; + $$->negated = TRUE; + } + ; + +user : ALIAS { + $$ = new_member($1, ALIAS); + } + | ALL { + $$ = new_member(NULL, ALL); + } + | NETGROUP { + $$ = new_member($1, NETGROUP); + } + | USERGROUP { + $$ = new_member($1, USERGROUP); + } + | WORD { + $$ = new_member($1, WORD); + } + ; + +grouplist : opgroup + | grouplist ',' opgroup { + list_append($1, $3); + $$ = $1; + } + ; + +opgroup : group { + $$ = $1; + $$->negated = FALSE; + } + | '!' group { + $$ = $2; + $$->negated = TRUE; + } + ; + +group : ALIAS { + $$ = new_member($1, ALIAS); + } + | ALL { + $$ = new_member(NULL, ALL); + } + | WORD { + $$ = new_member($1, WORD); + } + ; + +%% +static struct defaults * +new_default(var, val, op) + char *var; + char *val; + int op; +{ + struct defaults *d; + + d = emalloc(sizeof(struct defaults)); + d->var = var; + d->val = val; + tq_init(&d->binding); + d->type = 0; + d->op = op; + d->prev = d; + d->next = NULL; + + return(d); +} + +static struct member * +new_member(name, type) + char *name; + int type; +{ + struct member *m; + + m = emalloc(sizeof(struct member)); + m->name = name; + m->type = type; + m->prev = m; + m->next = NULL; + + return(m); +} + +/* + * Add a list of defaults structures to the defaults list. + * The binding, if non-NULL, specifies a list of hosts, users, or + * runas users the entries apply to (specified by the type). + */ +static void +add_defaults(type, bmem, defs) + int type; + struct member *bmem; + struct defaults *defs; +{ + struct defaults *d; + struct member_list binding; + + /* + * We can only call list2tq once on bmem as it will zero + * out the prev pointer when it consumes bmem. + */ + list2tq(&binding, bmem); + + /* + * Set type and binding (who it applies to) for new entries. + */ + for (d = defs; d != NULL; d = d->next) { + d->type = type; + d->binding = binding; + } + tq_append(&defaults, defs); +} + +/* + * Allocate a new struct userspec, populate it, and insert it at the + * and of the userspecs list. + */ +static void +add_userspec(members, privs) + struct member *members; + struct privilege *privs; +{ + struct userspec *u; + + u = emalloc(sizeof(*u)); + list2tq(&u->users, members); + list2tq(&u->privileges, privs); + u->prev = u; + u->next = NULL; + tq_append(&userspecs, u); +} + +/* + * Free up space used by data structures from a previous parser run and sets + * the current sudoers file to path. + */ +void +init_parser(path, quiet) + char *path; + int quiet; +{ + struct defaults *d; + struct member *m, *binding; + struct userspec *us; + struct privilege *priv; + struct cmndspec *cs; + struct sudo_command *c; + + while ((us = tq_pop(&userspecs)) != NULL) { + while ((m = tq_pop(&us->users)) != NULL) { + efree(m->name); + efree(m); + } + while ((priv = tq_pop(&us->privileges)) != NULL) { + struct member *runasuser = NULL, *runasgroup = NULL; +#ifdef HAVE_SELINUX + char *role = NULL, *type = NULL; +#endif /* HAVE_SELINUX */ + + while ((m = tq_pop(&priv->hostlist)) != NULL) { + efree(m->name); + efree(m); + } + while ((cs = tq_pop(&priv->cmndlist)) != NULL) { +#ifdef HAVE_SELINUX + /* Only free the first instance of a role/type. */ + if (cs->role != role) { + role = cs->role; + efree(cs->role); + } + if (cs->type != type) { + type = cs->type; + efree(cs->type); + } +#endif /* HAVE_SELINUX */ + if (tq_last(&cs->runasuserlist) != runasuser) { + runasuser = tq_last(&cs->runasuserlist); + while ((m = tq_pop(&cs->runasuserlist)) != NULL) { + efree(m->name); + efree(m); + } + } + if (tq_last(&cs->runasgrouplist) != runasgroup) { + runasgroup = tq_last(&cs->runasgrouplist); + while ((m = tq_pop(&cs->runasgrouplist)) != NULL) { + efree(m->name); + efree(m); + } + } + if (cs->cmnd->type == COMMAND) { + c = (struct sudo_command *) cs->cmnd->name; + efree(c->cmnd); + efree(c->args); + } + efree(cs->cmnd->name); + efree(cs->cmnd); + efree(cs); + } + efree(priv); + } + efree(us); + } + tq_init(&userspecs); + + binding = NULL; + while ((d = tq_pop(&defaults)) != NULL) { + if (tq_last(&d->binding) != binding) { + binding = tq_last(&d->binding); + while ((m = tq_pop(&d->binding)) != NULL) { + if (m->type == COMMAND) { + c = (struct sudo_command *) m->name; + efree(c->cmnd); + efree(c->args); + } + efree(m->name); + efree(m); + } + } + efree(d->var); + efree(d->val); + efree(d); + } + tq_init(&defaults); + + init_aliases(); + + efree(sudoers); + sudoers = path ? estrdup(path) : NULL; + + parse_error = FALSE; + errorlineno = -1; + sudolineno = 1; + verbose = !quiet; +} diff --git a/indent.pro b/indent.pro index b8269d8..db27ed3 100644 --- a/indent.pro +++ b/indent.pro @@ -1,13 +1,14 @@ --di4 -br -cdb -ce -d0 +-di1 -ei --lp +-i4 +-nlp -npcs --ps -npsl +-ps -sc -TYYSTYPE -TLIST diff --git a/ins_csops.h b/ins_csops.h index 9eb83d3..e94d8ae 100644 --- a/ins_csops.h +++ b/ins_csops.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 1996, 1998, 1999 Todd C. Miller + * Copyright (c) 1996, 1998, 1999, 2004 + * 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 +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: ins_csops.h,v 1.28.2.1 2007/06/10 16:57:35 millert Exp $ + * $Sudo: ins_csops.h,v 1.30 2008/11/09 14:13:12 millert Exp $ */ #ifndef _SUDO_INS_CSOPS_H diff --git a/install-sh b/install-sh index da07719..6dcd300 100755 --- a/install-sh +++ b/install-sh @@ -1,7 +1,7 @@ #! /bin/sh ## (From INN-1.4, written by Rich Salz) -## $Revision: 1.9.4.1 $ +## $Revision: 1.10 $ ## A script to install files and directories. PROGNAME=`basename $0` diff --git a/insults.h b/insults.h index 9b0c30f..113fe36 100644 --- a/insults.h +++ b/insults.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 1994-1996,1998-1999 Todd C. Miller + * Copyright (c) 1994-1996, 1998-1999, 2004 + * 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 +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: insults.h,v 1.46 2004/02/13 21:36:43 millert Exp $ + * $Sudo: insults.h,v 1.47 2008/11/09 14:13:12 millert Exp $ */ #ifndef _SUDO_INSULTS_H diff --git a/interfaces.c b/interfaces.c index 87abfaa..27ca438 100644 --- a/interfaces.c +++ b/interfaces.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1996, 1998-2005 Todd C. Miller + * Copyright (c) 1996, 1998-2005, 2007-2008 + * 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 @@ -59,11 +60,6 @@ struct rtentry; #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #include #ifdef _ISC @@ -89,7 +85,7 @@ struct rtentry; #include "interfaces.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: interfaces.c,v 1.72.2.8 2007/11/27 17:06:53 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: interfaces.c,v 1.84 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ @@ -193,7 +189,7 @@ load_interfaces() sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) - err(1, "cannot open socket"); + error(1, "cannot open socket"); /* * Get interface configuration or return (leaving num_interfaces == 0) @@ -249,7 +245,7 @@ load_interfaces() continue; #ifdef SIOCGIFFLAGS - memset(&ifr_tmp, 0, sizeof(ifr_tmp)); + zero_bytes(&ifr_tmp, sizeof(ifr_tmp)); strncpy(ifr_tmp.ifr_name, ifr->ifr_name, sizeof(ifr_tmp.ifr_name) - 1); if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr_tmp) < 0) #endif @@ -267,7 +263,7 @@ load_interfaces() previfname = ifr->ifr_name; /* Get the netmask. */ - (void) memset(&ifr_tmp, 0, sizeof(ifr_tmp)); + zero_bytes(&ifr_tmp, sizeof(ifr_tmp)); strncpy(ifr_tmp.ifr_name, ifr->ifr_name, sizeof(ifr_tmp.ifr_name) - 1); #ifdef SIOCGIFNETMASK #ifdef _ISC diff --git a/interfaces.h b/interfaces.h index ddb6f84..d4d4dd0 100644 --- a/interfaces.h +++ b/interfaces.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 1996, 1998-2004 Todd C. Miller + * Copyright (c) 1996, 1998-2005, 2007 + * 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 @@ -17,7 +18,7 @@ * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. * - * $Sudo: interfaces.h,v 1.8.2.3 2007/10/24 16:43:27 millert Exp $ + * $Sudo: interfaces.h,v 1.12 2008/11/09 14:13:12 millert Exp $ */ #ifndef _SUDO_INTERFACES_H diff --git a/isblank.c b/isblank.c new file mode 100644 index 0000000..02b15fe --- /dev/null +++ b/isblank.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2008 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 + +#ifndef lint +__unused static const char rcsid[] = "$Sudo: isblank.c,v 1.1 2008/11/06 00:05:24 millert Exp $"; +#endif /* lint */ + +#undef isblank +int +isblank(ch) + int ch; +{ + return(ch == ' ' || ch == '\t'); +} diff --git a/lbuf.c b/lbuf.c new file mode 100644 index 0000000..ef898eb --- /dev/null +++ b/lbuf.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2007-2008 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. + */ + +#include + +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include + +#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 $"; +#endif /* lint */ + +#if !defined(TIOCGSIZE) && defined(TIOCGWINSZ) +# define TIOCGSIZE TIOCGWINSZ +# define ttysize winsize +# define ts_cols ws_col +#endif + +int +get_ttycols() +{ + char *p; + int cols; +#ifdef TIOCGSIZE + struct ttysize win; + + if (ioctl(STDERR_FILENO, TIOCGSIZE, &win) == 0 && win.ts_cols != 0) + return((int)win.ts_cols); +#endif + + /* Fall back on $COLUMNS. */ + if ((p = getenv("COLUMNS")) == NULL || (cols = atoi(p)) <= 0) + cols = 80; + return(cols); +} + +/* + * TODO: add support for embedded newlines in lbufs + */ + +void +lbuf_init(lbuf, buf, indent, continuation) + struct lbuf *lbuf; + char *buf; + int indent; + int continuation; +{ + lbuf->continuation = continuation; + lbuf->indent = indent; + lbuf->len = 0; + lbuf->size = 0; + lbuf->buf = NULL; +} + +void +lbuf_destroy(lbuf) + struct lbuf *lbuf; +{ + efree(lbuf->buf); + lbuf->buf = NULL; +} + +/* + * Append strings to the buffer, expanding it as needed. + */ +void +#ifdef __STDC__ +lbuf_append_quoted(struct lbuf *lbuf, const char *set, ...) +#else +lbuf_append_quoted(lbuf, set, va_alist) + struct lbuf *lbuf; + const char *set; + va_dcl +#endif +{ + va_list ap; + int len = 0; + char *cp, *s; + +#ifdef __STDC__ + va_start(ap, set); +#else + va_start(ap); +#endif + while ((s = va_arg(ap, char *)) != NULL) { + len += strlen(s); + for (cp = s; (cp = strpbrk(cp, set)) != NULL; cp++) + len++; + } + va_end(ap); + + /* Expand buffer as needed. */ + if (lbuf->len + len >= lbuf->size) { + do { + lbuf->size += 256; + } while (lbuf->len + len >= lbuf->size); + lbuf->buf = erealloc(lbuf->buf, lbuf->size); + } + +#ifdef __STDC__ + va_start(ap, set); +#else + va_start(ap); +#endif + /* Append each string. */ + while ((s = va_arg(ap, char *)) != NULL) { + while ((cp = strpbrk(s, set)) != NULL) { + len = (int)(cp - s); + memcpy(lbuf->buf + lbuf->len, s, len); + lbuf->len += len; + lbuf->buf[lbuf->len++] = '\\'; + lbuf->buf[lbuf->len++] = *cp; + s = cp + 1; + } + if (*s != '\0') { + len = strlen(s); + memcpy(lbuf->buf + lbuf->len, s, len); + lbuf->len += len; + } + } + lbuf->buf[lbuf->len] = '\0'; + va_end(ap); +} + +/* + * Append strings to the buffer, expanding it as needed. + */ +void +#ifdef __STDC__ +lbuf_append(struct lbuf *lbuf, ...) +#else +lbuf_append(lbuf, va_alist) + struct lbuf *lbuf; + va_dcl +#endif +{ + va_list ap; + int len = 0; + char *s; + +#ifdef __STDC__ + va_start(ap, lbuf); +#else + va_start(ap); +#endif + while ((s = va_arg(ap, char *)) != NULL) + len += strlen(s); + va_end(ap); + + /* Expand buffer as needed. */ + if (lbuf->len + len >= lbuf->size) { + do { + lbuf->size += 256; + } while (lbuf->len + len >= lbuf->size); + lbuf->buf = erealloc(lbuf->buf, lbuf->size); + } + +#ifdef __STDC__ + va_start(ap, lbuf); +#else + va_start(ap); +#endif + /* Append each string. */ + while ((s = va_arg(ap, char *)) != NULL) { + len = strlen(s); + memcpy(lbuf->buf + lbuf->len, s, len); + lbuf->len += len; + } + lbuf->buf[lbuf->len] = '\0'; + va_end(ap); +} + +/* + * Print the buffer with word wrap based on the tty width. + * The lbuf is reset on return. + */ +void +lbuf_print(lbuf) + struct lbuf *lbuf; +{ + char *cp; + int i, have, contlen; + static int cols = -1; + + if (cols == -1) + cols = get_ttycols(); + contlen = lbuf->continuation ? 2 : 0; + + /* For very small widths just give up... */ + if (cols <= lbuf->indent + contlen + 20) { + puts(lbuf->buf); + goto done; + } + + /* + * Print the buffer, splitting the line as needed on a word + * boundary. + */ + cp = lbuf->buf; + have = cols; + while (cp != NULL && *cp != '\0') { + char *ep = NULL; + int need = lbuf->len - (int)(cp - lbuf->buf); + + if (need > have) { + have -= contlen; /* subtract for continuation char */ + if ((ep = memrchr(cp, ' ', have)) == NULL) + ep = memchr(cp + have, ' ', need - have); + if (ep != NULL) + need = (int)(ep - cp); + } + if (cp != lbuf->buf) { + /* indent continued lines */ + for (i = 0; i < lbuf->indent; i++) + putchar(' '); + } + fwrite(cp, need, 1, stdout); + cp = ep; + + /* + * If there is more to print, reset have, incremement cp past + * the whitespace, and print a line continuaton char if needed. + */ + if (cp != NULL) { + have = cols - lbuf->indent; + do { + cp++; + } while (isspace((unsigned char)*cp)); + if (lbuf->continuation) { + putchar(' '); + putchar(lbuf->continuation); + } + } + putchar('\n'); + } + +done: + lbuf->len = 0; /* reset the buffer for re-use. */ +} diff --git a/lbuf.h b/lbuf.h new file mode 100644 index 0000000..4633dee --- /dev/null +++ b/lbuf.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2007 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: lbuf.h,v 1.2 2007/08/22 22:31:07 millert Exp $" + */ + +#ifndef _SUDO_LBUF_H +#define _SUDO_LBUF_H + +/* + * Line buffer struct. + */ +struct lbuf { + char *buf; + int continuation; + int indent; + int len; + int size; +}; + +void lbuf_init __P((struct lbuf *, char *, int, int)); +void lbuf_destroy __P((struct lbuf *)); +void lbuf_append __P((struct lbuf *, ...)); +void lbuf_append_quoted __P((struct lbuf *, const char *, ...)); +void lbuf_print __P((struct lbuf *)); + +#endif /* _SUDO_LBUF_H */ diff --git a/ldap.c b/ldap.c index 8ee0ba7..c778f3a 100644 --- a/ldap.c +++ b/ldap.c @@ -45,18 +45,11 @@ # include #endif /* HAVE_UNISTD_H */ #include -#include #include #include #include #include #include -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ -#include #ifdef HAVE_LBER_H # include #endif @@ -66,18 +59,32 @@ #elif defined(HAVE_MPS_LDAP_SSL_H) # include #endif +#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S +# ifdef HAVE_SASL_SASL_H +# include +# else +# include +# endif +# if HAVE_GSS_KRB5_CCACHE_NAME +# if defined(HAVE_GSSAPI_GSSAPI_KRB5_H) +# include +# include +# elif defined(HAVE_GSSAPI_GSSAPI_H) +# include +# else +# include +# endif +# endif +#endif #include "sudo.h" #include "parse.h" +#include "lbuf.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: ldap.c,v 1.11.2.38 2008/04/11 14:03:51 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: ldap.c,v 1.100 2008/04/23 12:30:07 millert Exp $"; #endif /* lint */ -#ifndef LINE_MAX -# define LINE_MAX 2048 -#endif - #ifndef LDAP_OPT_SUCCESS # define LDAP_OPT_SUCCESS LDAP_SUCCESS #endif @@ -86,7 +93,25 @@ __unused static const char rcsid[] = "$Sudo: ldap.c,v 1.11.2.38 2008/04/11 14:03 # define LDAPS_PORT 636 #endif -#define DPRINTF(args, level) if (ldap_conf.debug >= level) warnx args +#if defined(HAVE_LDAP_SASL_INTERACTIVE_BIND_S) && !defined(LDAP_SASL_QUIET) +# define LDAP_SASL_QUIET 0 +#endif + +#ifndef HAVE_LDAP_UNBIND_EXT_S +#define ldap_unbind_ext_s(a, b, c) ldap_unbind_s(a) +#endif + +#ifndef HAVE_LDAP_SEARCH_EXT_S +#define ldap_search_ext_s(a, b, c, d, e, f, g, h, i, j, k) \ + ldap_search_s(a, b, c, d, e, f, k) +#endif + +#define LDAP_FOREACH(var, ld, res) \ + for ((var) = ldap_first_entry((ld), (res)); \ + (var) != NULL; \ + (var) = ldap_next_entry((ld), (var))) + +#define DPRINTF(args, level) if (ldap_conf.debug >= level) warningx args #define CONF_BOOL 0 #define CONF_INT 1 @@ -104,7 +129,7 @@ struct ldap_config_table { }; /* ldap configuration structure */ -struct ldap_config { +static struct ldap_config { int port; int version; int debug; @@ -112,6 +137,8 @@ struct ldap_config { int tls_checkpeer; int timelimit; int bind_timelimit; + int use_sasl; + int rootuse_sasl; int ssl_mode; char *host; char *uri; @@ -126,9 +153,13 @@ struct ldap_config { char *tls_cipher_suite; char *tls_certfile; char *tls_keyfile; + char *sasl_auth_id; + char *rootsasl_auth_id; + char *sasl_secprops; + char *krb5_ccname; } ldap_conf; -struct ldap_config_table ldap_conf_table[] = { +static struct ldap_config_table ldap_conf_table[] = { { "sudoers_debug", CONF_INT, FALSE, -1, &ldap_conf.debug }, { "host", CONF_STR, FALSE, -1, &ldap_conf.host }, { "port", CONF_INT, FALSE, -1, &ldap_conf.port }, @@ -188,12 +219,74 @@ struct ldap_config_table ldap_conf_table[] = { { "bindpw", CONF_STR, FALSE, -1, &ldap_conf.bindpw }, { "rootbinddn", CONF_STR, FALSE, -1, &ldap_conf.rootbinddn }, { "sudoers_base", CONF_STR, FALSE, -1, &ldap_conf.base }, +#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S + { "use_sasl", CONF_BOOL, FALSE, -1, &ldap_conf.use_sasl }, + { "sasl_auth_id", CONF_STR, FALSE, -1, &ldap_conf.sasl_auth_id }, + { "rootuse_sasl", CONF_BOOL, FALSE, -1, &ldap_conf.rootuse_sasl }, + { "rootsasl_auth_id", CONF_STR, FALSE, -1, &ldap_conf.rootsasl_auth_id }, +# ifdef LDAP_OPT_X_SASL_SECPROPS + { "sasl_secprops", CONF_STR, TRUE, LDAP_OPT_X_SASL_SECPROPS, + &ldap_conf.sasl_secprops }, +# endif + { "krb5_ccname", CONF_STR, FALSE, -1, &ldap_conf.krb5_ccname }, +#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */ { NULL } }; -static void sudo_ldap_update_defaults __P((LDAP *)); -static void sudo_ldap_close __P((LDAP *)); -static LDAP *sudo_ldap_open __P((void)); +struct sudo_nss sudo_nss_ldap = { + &sudo_nss_ldap, + NULL, + sudo_ldap_open, + sudo_ldap_close, + sudo_ldap_parse, + sudo_ldap_setdefs, + sudo_ldap_lookup, + sudo_ldap_display_cmnd, + sudo_ldap_display_defaults, + sudo_ldap_display_bound_defaults, + sudo_ldap_display_privs +}; + +#ifdef HAVE_LDAP_CREATE +/* + * Rebuild the hosts list and include a specific port for each host. + * ldap_create() does not take a default port parameter so we must + * append one if we want something other than LDAP_PORT. + */ +static void +sudo_ldap_conf_add_ports() +{ + + char *host, *port, defport[13]; + char hostbuf[LINE_MAX * 2]; + + hostbuf[0] = '\0'; + if (snprintf(defport, sizeof(defport), ":%d", ldap_conf.port) >= sizeof(defport)) + errorx(1, "sudo_ldap_conf_add_ports: port too large"); + + for ((host = strtok(ldap_conf.host, " \t")); host; (host = strtok(NULL, " \t"))) { + if (hostbuf[0] != '\0') { + if (strlcat(hostbuf, " ", sizeof(hostbuf)) >= sizeof(hostbuf)) + goto toobig; + } + + if (strlcat(hostbuf, host, sizeof(hostbuf)) >= sizeof(hostbuf)) + goto toobig; + /* Append port if there is not one already. */ + if ((port = strrchr(host, ':')) == NULL || !isdigit(port[1])) { + if (strlcat(hostbuf, defport, sizeof(hostbuf)) >= sizeof(hostbuf)) + goto toobig; + } + } + + free(ldap_conf.host); + ldap_conf.host = estrdup(hostbuf); + return; + +toobig: + errorx(1, "sudo_ldap_conf_add_ports: out of space expanding hostbuf"); +} +#endif #ifndef HAVE_LDAP_INITIALIZE /* @@ -220,7 +313,7 @@ sudo_ldap_parse_uri(uri_list) nldaps++; host = uri + 8; } else { - warnx("unsupported LDAP uri type: %s", uri); + warningx("unsupported LDAP uri type: %s", uri); goto done; } @@ -248,17 +341,17 @@ sudo_ldap_parse_uri(uri_list) } } if (hostbuf[0] == '\0') { - warnx("invalid uri: %s", uri_list); + warningx("invalid uri: %s", uri_list); goto done; } if (nldaps != 0) { if (nldap != 0) { - warnx("cannot mix ldap and ldaps URIs"); + warningx("cannot mix ldap and ldaps URIs"); goto done; } if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) { - warnx("cannot mix ldaps and starttls"); + warningx("cannot mix ldaps and starttls"); goto done; } ldap_conf.ssl_mode = SUDO_LDAP_SSL; @@ -273,7 +366,7 @@ done: return(rc); toobig: - errx(1, "sudo_ldap_parse_uri: out of space building hostbuf"); + errorx(1, "sudo_ldap_parse_uri: out of space building hostbuf"); } #endif /* HAVE_LDAP_INITIALIZE */ @@ -294,22 +387,29 @@ sudo_ldap_init(ldp, host, port) rc = ldapssl_clientauth_init(ldap_conf.tls_certfile, NULL, ldap_conf.tls_keyfile != NULL, ldap_conf.tls_keyfile, NULL); if (rc != LDAP_SUCCESS) { - warnx("unable to initialize SSL cert and key db: %s", + warningx("unable to initialize SSL cert and key db: %s", ldapssl_err2string(rc)); goto done; } DPRINTF(("ldapssl_init(%s, %d, 1)", host, port), 2); - if ((ld = ldapssl_init(host, port, 1)) == NULL) - goto done; + if ((ld = ldapssl_init(host, port, 1)) != NULL) + rc = LDAP_SUCCESS; } else #endif { - DPRINTF(("ldap_init(%s, %d)", host, port), 2); - if ((ld = ldap_init(host, port)) == NULL) +#ifdef HAVE_LDAP_CREATE + DPRINTF(("ldap_create()"), 2); + if ((rc = ldap_create(&ld)) != LDAP_SUCCESS) goto done; + DPRINTF(("ldap_set_option(LDAP_OPT_HOST_NAME, %s)", host), 2); + rc = ldap_set_option(ld, LDAP_OPT_HOST_NAME, host); +#else + DPRINTF(("ldap_init(%s, %d)", host, port), 2); + if ((ld = ldap_init(host, port)) != NULL) + rc = LDAP_SUCCESS; +#endif } - rc = LDAP_SUCCESS; done: *ldp = ld; @@ -321,30 +421,34 @@ done: * netgroup, else FALSE. */ int -sudo_ldap_check_user_netgroup(ld, entry) +sudo_ldap_check_user_netgroup(ld, entry, user) LDAP *ld; LDAPMessage *entry; + char *user; { - char **v = NULL, **p = NULL; + struct berval **bv, **p; + char *val; int ret = FALSE; if (!entry) return(ret); /* get the values from the entry */ - v = ldap_get_values(ld, entry, "sudoUser"); + bv = ldap_get_values_len(ld, entry, "sudoUser"); + if (bv == NULL) + return(ret); /* walk through values */ - for (p = v; p && *p && !ret; p++) { + for (p = bv; *p != NULL && !ret; p++) { + val = (*p)->bv_val; /* match any */ - if (netgr_matches(*p, NULL, NULL, user_name)) + if (netgr_matches(val, NULL, NULL, user)) ret = TRUE; - DPRINTF(("ldap sudoUser netgroup '%s' ... %s", *p, + DPRINTF(("ldap sudoUser netgroup '%s' ... %s", val, ret ? "MATCH!" : "not"), 2); } - if (v) - ldap_value_free(v); /* cleanup */ + ldap_value_free_len(bv); /* cleanup */ return(ret); } @@ -358,50 +462,51 @@ sudo_ldap_check_host(ld, entry) LDAP *ld; LDAPMessage *entry; { - char **v = NULL, **p = NULL; + struct berval **bv, **p; + char *val; int ret = FALSE; if (!entry) return(ret); /* get the values from the entry */ - v = ldap_get_values(ld, entry, "sudoHost"); + bv = ldap_get_values_len(ld, entry, "sudoHost"); + if (bv == NULL) + return(ret); /* walk through values */ - for (p = v; p && *p && !ret; p++) { + for (p = bv; *p != NULL && !ret; p++) { + val = (*p)->bv_val; /* match any or address or netgroup or hostname */ - if (!strcmp(*p, "ALL") || addr_matches(*p) || - netgr_matches(*p, user_host, user_shost, NULL) || - !hostname_matches(user_shost, user_host, *p)) + if (!strcmp(val, "ALL") || addr_matches(val) || + netgr_matches(val, user_host, user_shost, NULL) || + hostname_matches(user_shost, user_host, val)) ret = TRUE; - DPRINTF(("ldap sudoHost '%s' ... %s", *p, + DPRINTF(("ldap sudoHost '%s' ... %s", val, ret ? "MATCH!" : "not"), 2); } - if (v) - ldap_value_free(v); /* cleanup */ + ldap_value_free_len(bv); /* cleanup */ return(ret); } -/* - * Walk through search results and return TRUE if we have a runas match, - * else FALSE. - * Since the runas directive in /etc/sudoers is optional, so is sudoRunAs. - */ int -sudo_ldap_check_runas(ld, entry) +sudo_ldap_check_runas_user(ld, entry) LDAP *ld; LDAPMessage *entry; { - char **v = NULL, **p = NULL; + struct berval **bv, **p; + char *val; int ret = FALSE; - if (!entry) - return(ret); + if (!runas_pw) + return(UNSPEC); - /* get the values from the entry */ - v = ldap_get_values(ld, entry, "sudoRunAs"); + /* get the runas user from the entry */ + bv = ldap_get_values_len(ld, entry, "sudoRunAsUser"); + if (bv == NULL) + bv = ldap_get_values_len(ld, entry, "sudoRunAs"); /* old style */ /* * BUG: @@ -416,52 +521,104 @@ sudo_ldap_check_runas(ld, entry) * For now just require users to always use -u option unless its set * in the global defaults. This behaviour is no different than the global * /etc/sudoers. - * + * * Sigh - maybe add this feature later - * */ /* * If there are no runas entries, match runas_default against * what the user specified on the command line. */ - if (!v) - ret = !strcasecmp(runas_pw->pw_name, def_runas_default); + if (bv == NULL) + return(!strcasecmp(runas_pw->pw_name, def_runas_default)); /* walk through values returned, looking for a match */ - for (p = v; p && *p && !ret; p++) { - switch (*p[0]) { + for (p = bv; *p != NULL && !ret; p++) { + val = (*p)->bv_val; + switch (val[0]) { case '+': - if (netgr_matches(*p, NULL, NULL, runas_pw->pw_name)) + if (netgr_matches(val, NULL, NULL, runas_pw->pw_name)) ret = TRUE; break; case '%': - if (usergr_matches(*p, runas_pw->pw_name, runas_pw)) + if (usergr_matches(val, runas_pw->pw_name, runas_pw)) ret = TRUE; break; case 'A': - if (strcmp(*p, "ALL") == 0) { + if (strcmp(val, "ALL") == 0) { ret = TRUE; break; } /* FALLTHROUGH */ default: - if (strcasecmp(*p, runas_pw->pw_name) == 0) + if (strcasecmp(val, runas_pw->pw_name) == 0) ret = TRUE; break; } - DPRINTF(("ldap sudoRunAs '%s' ... %s", *p, + DPRINTF(("ldap sudoRunAsUser '%s' ... %s", val, ret ? "MATCH!" : "not"), 2); } - if (v) - ldap_value_free(v); /* cleanup */ + ldap_value_free_len(bv); /* cleanup */ + + return(ret); +} + +int +sudo_ldap_check_runas_group(ld, entry) + LDAP *ld; + LDAPMessage *entry; +{ + struct berval **bv, **p; + char *val; + int ret = FALSE; + + /* runas_gr is only set if the user specified the -g flag */ + if (!runas_gr) + return(UNSPEC); + + /* get the values from the entry */ + bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup"); + if (bv == NULL) + return(ret); + + /* walk through values returned, looking for a match */ + for (p = bv; *p != NULL && !ret; p++) { + val = (*p)->bv_val; + if (strcmp(val, "ALL") == 0 || group_matches(val, runas_gr)) + ret = TRUE; + DPRINTF(("ldap sudoRunAsGroup '%s' ... %s", val, + ret ? "MATCH!" : "not"), 2); + } + + ldap_value_free_len(bv); /* cleanup */ return(ret); } /* - * Walk through search results and return TRUE if we have a command match. + * Walk through search results and return TRUE if we have a runas match, + * else FALSE. RunAs info is optional. + */ +int +sudo_ldap_check_runas(ld, entry) + LDAP *ld; + LDAPMessage *entry; +{ + int ret; + + if (!entry) + return(FALSE); + + ret = sudo_ldap_check_runas_user(ld, entry) != FALSE && + sudo_ldap_check_runas_group(ld, entry) != FALSE; + + return(ret); +} + +/* + * Walk through search results and return TRUE if we have a command match, + * FALSE if disallowed and UNSPEC if not matched. */ int sudo_ldap_check_command(ld, entry, setenv_implied) @@ -469,32 +626,35 @@ sudo_ldap_check_command(ld, entry, setenv_implied) LDAPMessage *entry; int *setenv_implied; { - char *allowed_cmnd, *allowed_args, **v = NULL, **p = NULL; - int foundbang, ret = FALSE; + struct berval **bv, **p; + char *allowed_cmnd, *allowed_args, *val; + int foundbang, ret = UNSPEC; if (!entry) return(ret); - v = ldap_get_values(ld, entry, "sudoCommand"); + bv = ldap_get_values_len(ld, entry, "sudoCommand"); + if (bv == NULL) + return(ret); - /* get_first_entry */ - for (p = v; p && *p && ret >= 0; p++) { + for (p = bv; *p != NULL && ret != FALSE; p++) { + val = (*p)->bv_val; /* Match against ALL ? */ - if (!strcmp(*p, "ALL")) { + if (!strcmp(val, "ALL")) { ret = TRUE; if (setenv_implied != NULL) *setenv_implied = TRUE; - DPRINTF(("ldap sudoCommand '%s' ... MATCH!", *p), 2); + DPRINTF(("ldap sudoCommand '%s' ... MATCH!", val), 2); continue; } /* check for !command */ - if (**p == '!') { + if (*val == '!') { foundbang = TRUE; - allowed_cmnd = estrdup(1 + *p); /* !command */ + allowed_cmnd = estrdup(1 + val); /* !command */ } else { foundbang = FALSE; - allowed_cmnd = estrdup(*p); /* command */ + allowed_cmnd = estrdup(val); /* command */ } /* split optional args away from command */ @@ -508,19 +668,54 @@ sudo_ldap_check_command(ld, entry, setenv_implied) * If allowed (no bang) set ret but keep on checking. * If disallowed (bang), exit loop. */ - ret = foundbang ? -1 : TRUE; + ret = foundbang ? FALSE : TRUE; } - DPRINTF(("ldap sudoCommand '%s' ... %s", *p, + DPRINTF(("ldap sudoCommand '%s' ... %s", val, ret == TRUE ? "MATCH!" : "not"), 2); efree(allowed_cmnd); /* cleanup */ } - if (v) - ldap_value_free(v); /* more cleanup */ + ldap_value_free_len(bv); /* more cleanup */ - /* return TRUE if we found at least one ALLOW and no DENY */ - return(ret > 0); + return(ret); +} + +/* + * Search for boolean "option" in sudoOption. + * Returns TRUE if found and allowed, FALSE if negated, else UNSPEC. + */ +int +sudo_ldap_check_bool(ld, entry, option) + LDAP *ld; + LDAPMessage *entry; + char *option; +{ + struct berval **bv, **p; + char ch, *var; + int ret = UNSPEC; + + if (entry == NULL) + return(UNSPEC); + + bv = ldap_get_values_len(ld, entry, "sudoOption"); + if (bv == NULL) + return(ret); + + /* walk through options */ + for (p = bv; *p != NULL; p++) { + var = (*p)->bv_val;; + DPRINTF(("ldap sudoOption: '%s'", var), 2); + + if ((ch = *var) == '!') + var++; + if (strcmp(var, option) == 0) + ret = (ch != '!'); + } + + ldap_value_free_len(bv); + + return(ret); } /* @@ -532,18 +727,20 @@ sudo_ldap_parse_options(ld, entry) LDAP *ld; LDAPMessage *entry; { - char op, *var, *val, **v = NULL, **p = NULL; + struct berval **bv, **p; + char op, *var, *val; - if (!entry) + if (entry == NULL) return; - v = ldap_get_values(ld, entry, "sudoOption"); + bv = ldap_get_values_len(ld, entry, "sudoOption"); + if (bv == NULL) + return; /* walk through options */ - for (p = v; p && *p; p++) { - - DPRINTF(("ldap sudoOption: '%s'", *p), 2); - var = estrdup(*p); + for (p = bv; *p != NULL; p++) { + var = estrdup((*p)->bv_val); + DPRINTF(("ldap sudoOption: '%s'", var), 2); /* check for equals sign past first char */ val = strchr(var, '='); @@ -568,96 +765,63 @@ sudo_ldap_parse_options(ld, entry) efree(var); } - if (v) - ldap_value_free(v); -} - -/* - * Concatenate strings, dynamically growing them as necessary. - * Strings can be arbitrarily long and are allocated/reallocated on - * the fly. Make sure to free them when you are done. - * - * Usage: - * - * char *s=NULL; - * size_t sz; - * - * ncat(&s,&sz,"This "); - * ncat(&s,&sz,"is "); - * ncat(&s,&sz,"an "); - * ncat(&s,&sz,"arbitrarily "); - * ncat(&s,&sz,"long "); - * ncat(&s,&sz,"string!"); - * - * printf("String Value='%s', but has %d bytes allocated\n",s,sz); - * - */ -void -ncat(s, sz, src) - char **s; - size_t *sz; - char *src; -{ - size_t nsz; - - /* handle initial alloc */ - if (*s == NULL) { - *s = estrdup(src); - *sz = strlen(src) + 1; - return; - } - /* handle realloc */ - nsz = strlen(*s) + strlen(src) + 1; - if (*sz < nsz) - *s = erealloc((void *) *s, *sz = nsz * 2); - strlcat(*s, src, *sz); + ldap_value_free_len(bv); } /* * builds together a filter to check against ldap */ char * -sudo_ldap_build_pass1() +sudo_ldap_build_pass1(pw) + struct passwd *pw; { struct group *grp; size_t sz; - char *b = NULL; + char *buf; int i; - /* global OR */ - ncat(&b, &sz, "(|"); + /* Start with (|(sudoUser=USERNAME)(sudoUser=ALL)) + NUL */ + sz = 29 + strlen(pw->pw_name); - /* build filter sudoUser=user_name */ - ncat(&b, &sz, "(sudoUser="); - ncat(&b, &sz, user_name); - ncat(&b, &sz, ")"); + /* Add space for groups */ + if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) + sz += 12 + strlen(grp->gr_name); /* primary group */ + for (i = 0; i < user_ngroups; i++) { + if (user_groups[i] == pw->pw_gid) + continue; + if ((grp = sudo_getgrgid(user_groups[i])) != NULL) + sz += 12 + strlen(grp->gr_name); /* supplementary group */ + } + buf = emalloc(sz); + + /* Global OR + sudoUser=user_name filter */ + (void) strlcpy(buf, "(|(sudoUser=", sz); + (void) strlcat(buf, pw->pw_name, sz); + (void) strlcat(buf, ")", sz); /* Append primary group */ - grp = getgrgid(user_gid); - if (grp != NULL) { - ncat(&b, &sz, "(sudoUser=%"); - ncat(&b, &sz, grp -> gr_name); - ncat(&b, &sz, ")"); + if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) { + (void) strlcat(buf, "(sudoUser=%", sz); + (void) strlcat(buf, grp->gr_name, sz); + (void) strlcat(buf, ")", sz); } /* Append supplementary groups */ for (i = 0; i < user_ngroups; i++) { - if (user_groups[i] == user_gid) + if (user_groups[i] == pw->pw_gid) continue; - if ((grp = getgrgid(user_groups[i])) != NULL) { - ncat(&b, &sz, "(sudoUser=%"); - ncat(&b, &sz, grp -> gr_name); - ncat(&b, &sz, ")"); + if ((grp = sudo_getgrgid(user_groups[i])) != NULL) { + (void) strlcat(buf, "(sudoUser=%", sz); + (void) strlcat(buf, grp->gr_name, sz); + (void) strlcat(buf, ")", sz); } } - /* Add ALL to list */ - ncat(&b, &sz, "(sudoUser=ALL)"); - - /* End of OR List */ - ncat(&b, &sz, ")"); + /* Add ALL to list and end the global OR */ + if (strlcat(buf, "(sudoUser=ALL))", sz) >= sz) + errorx(1, "sudo_ldap_build_pass1 allocation mismatch"); - return(b); + return(buf); } /* @@ -699,11 +863,33 @@ _atobool(s) return(-1); } +static void +sudo_ldap_read_secret(path) + const char *path; +{ + FILE *fp; + char buf[LINE_MAX], *cp; + + if ((fp = fopen(_PATH_LDAP_SECRET, "r")) != NULL) { + if (fgets(buf, sizeof(buf), fp) != NULL) { + if ((cp = strchr(buf, '\n')) != NULL) + *cp = '\0'; + /* copy to bindpw and binddn */ + efree(ldap_conf.bindpw); + ldap_conf.bindpw = estrdup(buf); + efree(ldap_conf.binddn); + ldap_conf.binddn = ldap_conf.rootbinddn; + ldap_conf.rootbinddn = NULL; + } + fclose(fp); + } +} + int sudo_ldap_read_config() { - FILE *f; - char buf[LINE_MAX], *c, *keyword, *value; + FILE *fp; + char *cp, *keyword, *value; struct ldap_config_table *cur; /* defaults */ @@ -712,39 +898,27 @@ sudo_ldap_read_config() ldap_conf.tls_checkpeer = -1; ldap_conf.timelimit = -1; ldap_conf.bind_timelimit = -1; + ldap_conf.use_sasl = -1; + ldap_conf.rootuse_sasl = -1; - if ((f = fopen(_PATH_LDAP_CONF, "r")) == NULL) + if ((fp = fopen(_PATH_LDAP_CONF, "r")) == NULL) return(FALSE); - while (fgets(buf, sizeof(buf), f)) { - /* ignore text after comment character */ - if ((c = strchr(buf, '#')) != NULL) - *c = '\0'; - - /* skip leading whitespace */ - for (c = buf; isspace((unsigned char) *c); c++) - /* nothing */; - - if (*c == '\0' || *c == '\n') + while ((cp = sudo_parseln(fp)) != NULL) { + if (*cp == '\0') continue; /* skip empty line */ - /* properly terminate keyword string */ - keyword = c; - while (*c && !isspace((unsigned char) *c)) - c++; - if (*c) - *c++ = '\0'; /* terminate keyword */ + /* split into keyword and value */ + keyword = cp; + while (*cp && !isblank((unsigned char) *cp)) + cp++; + if (*cp) + *cp++ = '\0'; /* terminate keyword */ /* skip whitespace before value */ - while (isspace((unsigned char) *c)) - c++; - value = c; - - /* trim whitespace after value */ - while (*c) - c++; /* wind to end */ - while (--c > value && isspace((unsigned char) *c)) - *c = '\0'; + while (isblank((unsigned char) *cp)) + cp++; + value = cp; /* Look up keyword in config table. */ for (cur = ldap_conf_table; cur->conf_str != NULL; cur++) { @@ -765,10 +939,10 @@ sudo_ldap_read_config() } } } - fclose(f); + fclose(fp); if (!ldap_conf.host) - ldap_conf.host = "localhost"; + ldap_conf.host = estrdup("localhost"); if (ldap_conf.bind_timelimit > 0) ldap_conf.bind_timelimit *= 1000; /* convert to ms */ @@ -777,25 +951,25 @@ sudo_ldap_read_config() fprintf(stderr, "LDAP Config Summary\n"); fprintf(stderr, "===================\n"); if (ldap_conf.uri) { - fprintf(stderr, "uri %s\n", ldap_conf.uri); + fprintf(stderr, "uri %s\n", ldap_conf.uri); } else { - fprintf(stderr, "host %s\n", ldap_conf.host ? + fprintf(stderr, "host %s\n", ldap_conf.host ? ldap_conf.host : "(NONE)"); - fprintf(stderr, "port %d\n", ldap_conf.port); + fprintf(stderr, "port %d\n", ldap_conf.port); } - fprintf(stderr, "ldap_version %d\n", ldap_conf.version); + fprintf(stderr, "ldap_version %d\n", ldap_conf.version); - fprintf(stderr, "sudoers_base %s\n", ldap_conf.base ? + fprintf(stderr, "sudoers_base %s\n", ldap_conf.base ? ldap_conf.base : "(NONE) <---Sudo will ignore ldap)"); - fprintf(stderr, "binddn %s\n", ldap_conf.binddn ? + fprintf(stderr, "binddn %s\n", ldap_conf.binddn ? ldap_conf.binddn : "(anonymous)"); - fprintf(stderr, "bindpw %s\n", ldap_conf.bindpw ? + fprintf(stderr, "bindpw %s\n", ldap_conf.bindpw ? ldap_conf.bindpw : "(anonymous)"); if (ldap_conf.bind_timelimit > 0) - fprintf(stderr, "bind_timelimit %d\n", ldap_conf.bind_timelimit); + fprintf(stderr, "bind_timelimit %d\n", ldap_conf.bind_timelimit); if (ldap_conf.timelimit > 0) - fprintf(stderr, "timelimit %d\n", ldap_conf.timelimit); - fprintf(stderr, "ssl %s\n", ldap_conf.ssl ? + fprintf(stderr, "timelimit %d\n", ldap_conf.timelimit); + fprintf(stderr, "ssl %s\n", ldap_conf.ssl ? ldap_conf.ssl : "(no)"); if (ldap_conf.tls_checkpeer != -1) fprintf(stderr, "tls_checkpeer %s\n", ldap_conf.tls_checkpeer ? @@ -812,6 +986,21 @@ sudo_ldap_read_config() fprintf(stderr, "tls_certfile %s\n", ldap_conf.tls_certfile); if (ldap_conf.tls_keyfile != NULL) fprintf(stderr, "tls_keyfile %s\n", ldap_conf.tls_keyfile); +#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S + if (ldap_conf.use_sasl != -1) { + fprintf(stderr, "use_sasl %s\n", + ldap_conf.use_sasl ? "yes" : "no"); + fprintf(stderr, "sasl_auth_id %s\n", ldap_conf.sasl_auth_id ? + ldap_conf.sasl_auth_id : "(NONE)"); + fprintf(stderr, "rootuse_sasl %d\n", ldap_conf.rootuse_sasl); + fprintf(stderr, "rootsasl_auth_id %s\n", ldap_conf.rootsasl_auth_id ? + ldap_conf.rootsasl_auth_id : "(NONE)"); + fprintf(stderr, "sasl_secprops %s\n", ldap_conf.sasl_secprops ? + ldap_conf.sasl_secprops : "(NONE)"); + fprintf(stderr, "krb5_ccname %s\n", ldap_conf.krb5_ccname ? + ldap_conf.krb5_ccname : "(NONE)"); + } +#endif fprintf(stderr, "===================\n"); } if (!ldap_conf.base) @@ -845,124 +1034,441 @@ sudo_ldap_read_config() } #endif - /* Use port 389 for plaintext LDAP and port 636 for SSL LDAP */ - if (!ldap_conf.uri && ldap_conf.port < 0) - ldap_conf.port = - ldap_conf.ssl_mode == SUDO_LDAP_SSL ? LDAPS_PORT : LDAP_PORT; + if (!ldap_conf.uri) { + /* Use port 389 for plaintext LDAP and port 636 for SSL LDAP */ + if (ldap_conf.port < 0) + ldap_conf.port = + ldap_conf.ssl_mode == SUDO_LDAP_SSL ? LDAPS_PORT : LDAP_PORT; + +#ifdef HAVE_LDAP_CREATE + /* + * Cannot specify port directly to ldap_create(), each host must + * include :port to override the default. + */ + if (ldap_conf.port != LDAP_PORT) + sudo_ldap_conf_add_ports(); +#endif + } /* If rootbinddn set, read in /etc/ldap.secret if it exists. */ - if (ldap_conf.rootbinddn) { - if ((f = fopen(_PATH_LDAP_SECRET, "r")) != NULL) { - if (fgets(buf, sizeof(buf), f) != NULL) { - /* removing trailing newlines */ - for (c = buf; *c != '\0'; c++) - continue; - while (--c > buf && *c == '\n') - *c = '\0'; - /* copy to bindpw and binddn */ - efree(ldap_conf.bindpw); - ldap_conf.bindpw = estrdup(buf); - efree(ldap_conf.binddn); - ldap_conf.binddn = ldap_conf.rootbinddn; - ldap_conf.rootbinddn = NULL; + if (ldap_conf.rootbinddn) + sudo_ldap_read_secret(_PATH_LDAP_SECRET); + +#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S + /* + * Make sure we can open the file specified by krb5_ccname. + */ + if (ldap_conf.krb5_ccname != NULL) { + if (strncasecmp(ldap_conf.krb5_ccname, "FILE:", 5) == 0 || + strncasecmp(ldap_conf.krb5_ccname, "WRFILE:", 7) == 0) { + value = ldap_conf.krb5_ccname + + (ldap_conf.krb5_ccname[4] == ':' ? 5 : 7); + if ((fp = fopen(value, "r")) != NULL) { + DPRINTF(("using krb5 credential cache: %s", value), 1); + fclose(fp); + } else { + /* Can't open it, just ignore the entry. */ + DPRINTF(("unable to open krb5 credential cache: %s", value), 1); + efree(ldap_conf.krb5_ccname); + ldap_conf.krb5_ccname = NULL; } - fclose(f); } } +#endif return(TRUE); } /* - * like perl's join(sep,@ARGS) + * Extract the dn from an entry and return the first rdn from it. */ -char * - _ldap_join_values(sep, v) - char *sep; - char **v; +static char * +sudo_ldap_get_first_rdn(ld, entry) + LDAP *ld; + LDAPMessage *entry; { - char *b = NULL, **p = NULL; - size_t sz = 0; - - /* paste values together */ - for (p = v; p && *p; p++) { - if (p != v && sep != NULL) - ncat(&b, &sz, sep); /* append separator */ - ncat(&b, &sz, *p); /* append value */ +#ifdef HAVE_LDAP_STR2DN + char *dn, *rdn = NULL; + LDAPDN tmpDN; + + if ((dn = ldap_get_dn(ld, entry)) == NULL) + return(NULL); + if (ldap_str2dn(dn, &tmpDN, LDAP_DN_FORMAT_LDAP) == LDAP_SUCCESS) { + ldap_rdn2str(tmpDN[0], &rdn, LDAP_DN_FORMAT_UFN); + ldap_dnfree(tmpDN); } + ldap_memfree(dn); + return(rdn); +#else + char *dn, **edn; + + if ((dn = ldap_get_dn(ld, entry)) == NULL) + return(NULL); + edn = ldap_explode_dn(dn, 1); + ldap_memfree(dn); + return(edn ? edn[0] : NULL); +#endif +} - /* sanity check */ - if (b[0] == '\0') { - /* something went wrong, put something here */ - ncat(&b, &sz, "(empty list)"); /* append value */ +/* + * Fetch and display the global Options. + */ +int +sudo_ldap_display_defaults(nss, pw, lbuf) + struct sudo_nss *nss; + struct passwd *pw; + struct lbuf *lbuf; +{ + struct berval **bv, **p; + LDAP *ld = (LDAP *) nss->handle; + LDAPMessage *entry = NULL, *result = NULL; + char *prefix = NULL; + int rc, count = 0; + + if (ld == NULL) + return(-1); + + rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, + "cn=defaults", NULL, 0, NULL, NULL, NULL, -1, &result); + if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) { + bv = ldap_get_values_len(ld, entry, "sudoOption"); + if (bv != NULL) { + if (lbuf->len == 0) + prefix = " "; + else + prefix = ", "; + for (p = bv; *p != NULL; p++) { + lbuf_append(lbuf, prefix, (*p)->bv_val, NULL); + prefix = ", "; + count++; + } + ldap_value_free_len(bv); + } } + if (result) + ldap_msgfree(result); + return(count); +} - return(b); +/* + * STUB + */ +int +sudo_ldap_display_bound_defaults(nss, pw, lbuf) + struct sudo_nss *nss; + struct passwd *pw; + struct lbuf *lbuf; +{ + return(1); } -char *sudo_ldap_cm_list = NULL; -size_t sudo_ldap_cm_list_size; +/* + * Print a record in the short form, ala file sudoers. + */ +int +sudo_ldap_display_entry_short(ld, entry, lbuf) + LDAP *ld; + LDAPMessage *entry; + struct lbuf *lbuf; +{ + struct berval **bv, **p; + int count = 0; + + lbuf_append(lbuf, " (", NULL); + + /* get the RunAsUser Values from the entry */ + bv = ldap_get_values_len(ld, entry, "sudoRunAsUser"); + if (bv == NULL) + bv = ldap_get_values_len(ld, entry, "sudoRunAs"); + if (bv != NULL) { + for (p = bv; *p != NULL; p++) { + if (p != bv) + lbuf_append(lbuf, ", ", NULL); + lbuf_append(lbuf, (*p)->bv_val, NULL); + } + ldap_value_free_len(bv); + } else + lbuf_append(lbuf, def_runas_default, NULL); + + /* get the RunAsGroup Values from the entry */ + bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup"); + if (bv != NULL) { + lbuf_append(lbuf, " : ", NULL); + for (p = bv; *p != NULL; p++) { + if (p != bv) + lbuf_append(lbuf, ", ", NULL); + lbuf_append(lbuf, (*p)->bv_val, NULL); + } + ldap_value_free_len(bv); + } + lbuf_append(lbuf, ") ", NULL); + + /* get the Option Values from the entry */ + bv = ldap_get_values_len(ld, entry, "sudoOption"); + if (bv != NULL) { + char *cp, *tag; + + for (p = bv; *p != NULL; p++) { + cp = (*p)->bv_val; + if (*cp == '!') + cp++; + tag = NULL; + if (strcmp(cp, "authenticate") == 0) + tag = (*p)->bv_val[0] == '!' ? + "NOPASSWD: " : "PASSWD: "; + else if (strcmp(cp, "noexec") == 0) + tag = (*p)->bv_val[0] == '!' ? + "EXEC: " : "NOEXEC: "; + else if (strcmp(cp, "setenv") == 0) + tag = (*p)->bv_val[0] == '!' ? + "NOSETENV: " : "SETENV: "; + if (tag != NULL) + lbuf_append(lbuf, tag, NULL); + /* XXX - ignores other options */ + } + ldap_value_free_len(bv); + } + + /* get the Command Values from the entry */ + bv = ldap_get_values_len(ld, entry, "sudoCommand"); + if (bv != NULL) { + for (p = bv; *p != NULL; p++) { + if (p != bv) + lbuf_append(lbuf, ", ", NULL); + lbuf_append(lbuf, (*p)->bv_val, NULL); + count++; + } + ldap_value_free_len(bv); + } + + lbuf_print(lbuf); /* forces a newline */ + return(count); +} -#define SAVE_LIST(x) ncat(&sudo_ldap_cm_list,&sudo_ldap_cm_list_size,(x)) /* - * Walks through search result and returns TRUE if we have a - * command match + * Print a record in the long form. */ int -sudo_ldap_add_match(ld, entry, pwflag) +sudo_ldap_display_entry_long(ld, entry, lbuf) LDAP *ld; LDAPMessage *entry; - int pwflag; + struct lbuf *lbuf; { - char *dn, **edn, **v = NULL; - - /* if we are not collecting matches, then don't save them */ - if (pwflag != I_LISTPW) - return(TRUE); - - /* collect the dn, only show the rdn */ - dn = ldap_get_dn(ld, entry); - edn = dn ? ldap_explode_dn(dn, 1) : NULL; - SAVE_LIST("\nLDAP Role: "); - SAVE_LIST((edn && *edn) ? *edn : "UNKNOWN"); - SAVE_LIST("\n"); - if (dn) - ldap_memfree(dn); - if (edn) - ldap_value_free(edn); - - /* get the Runas Values from the entry */ - v = ldap_get_values(ld, entry, "sudoRunAs"); - if (v && *v) { - SAVE_LIST(" RunAs: ("); - SAVE_LIST(_ldap_join_values(", ", v)); - SAVE_LIST(")\n"); + struct berval **bv, **p; + char *rdn; + int count = 0; + + /* extract the dn, only show the first rdn */ + rdn = sudo_ldap_get_first_rdn(ld, entry); + lbuf_print(lbuf); /* force a newline */ + lbuf_append(lbuf, "LDAP Role: ", rdn ? rdn : "UNKNOWN", NULL); + lbuf_print(lbuf); + if (rdn) + ldap_memfree(rdn); + + /* get the RunAsUser Values from the entry */ + lbuf_append(lbuf, " RunAsUsers: ", NULL); + bv = ldap_get_values_len(ld, entry, "sudoRunAsUser"); + if (bv == NULL) + bv = ldap_get_values_len(ld, entry, "sudoRunAs"); + if (bv != NULL) { + for (p = bv; *p != NULL; p++) { + if (p != bv) + lbuf_append(lbuf, ", ", NULL); + lbuf_append(lbuf, (*p)->bv_val, NULL); + } + ldap_value_free_len(bv); + } else + lbuf_append(lbuf, def_runas_default, NULL); + lbuf_print(lbuf); + + /* get the RunAsGroup Values from the entry */ + bv = ldap_get_values_len(ld, entry, "sudoRunAsGroup"); + if (bv != NULL) { + lbuf_append(lbuf, " RunAsGroups: ", NULL); + for (p = bv; *p != NULL; p++) { + if (p != bv) + lbuf_append(lbuf, ", ", NULL); + lbuf_append(lbuf, (*p)->bv_val, NULL); + } + ldap_value_free_len(bv); + lbuf_print(lbuf); + } + + /* get the Option Values from the entry */ + bv = ldap_get_values_len(ld, entry, "sudoOption"); + if (bv != NULL) { + lbuf_append(lbuf, " Options: ", NULL); + for (p = bv; *p != NULL; p++) { + if (p != bv) + lbuf_append(lbuf, ", ", NULL); + lbuf_append(lbuf, (*p)->bv_val, NULL); + } + ldap_value_free_len(bv); + lbuf_print(lbuf); } - if (v) - ldap_value_free(v); /* get the Command Values from the entry */ - v = ldap_get_values(ld, entry, "sudoCommand"); - if (v && *v) { - SAVE_LIST(" Commands:\n "); - SAVE_LIST(_ldap_join_values("\n ", v)); - SAVE_LIST("\n"); - } else { - SAVE_LIST(" Commands: NONE\n"); + bv = ldap_get_values_len(ld, entry, "sudoCommand"); + if (bv != NULL) { + lbuf_append(lbuf, " Commands:", NULL); + lbuf_print(lbuf); + for (p = bv; *p != NULL; p++) { + lbuf_append(lbuf, "\t", (*p)->bv_val, NULL); + lbuf_print(lbuf); + count++; + } + ldap_value_free_len(bv); } - if (v) - ldap_value_free(v); - return(FALSE); /* Don't stop at the first match */ + return(count); } -#undef SAVE_LIST -void -sudo_ldap_list_matches() +/* + * Like sudo_ldap_lookup(), except we just print entries. + */ +int +sudo_ldap_display_privs(nss, pw, lbuf) + struct sudo_nss *nss; + struct passwd *pw; + struct lbuf *lbuf; { - if (sudo_ldap_cm_list != NULL) - printf("%s", sudo_ldap_cm_list); + LDAP *ld = (LDAP *) nss->handle; + LDAPMessage *entry = NULL, *result = NULL; + char *filt; + int rc, do_netgr, count = 0; + + if (ld == NULL) + return(-1); + + /* + * Okay - time to search for anything that matches this user + * Lets limit it to only two queries of the LDAP server + * + * The first pass will look by the username, groups, and + * the keyword ALL. We will then inspect the results that + * came back from the query. We don't need to inspect the + * sudoUser in this pass since the LDAP server already scanned + * it for us. + * + * The second pass will return all the entries that contain + * user netgroups. Then we take the netgroups returned and + * try to match them against the username. + */ + for (do_netgr = 0; do_netgr < 2; do_netgr++) { + 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); + efree(filt); + if (rc != LDAP_SUCCESS) + continue; /* no entries for this pass */ + + /* print each matching entry */ + LDAP_FOREACH(entry, ld, result) { + if ((!do_netgr || + sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) && + sudo_ldap_check_host(ld, entry)) { + + if (long_list) + count += sudo_ldap_display_entry_long(ld, entry, lbuf); + else + count += sudo_ldap_display_entry_short(ld, entry, lbuf); + } + } + ldap_msgfree(result); + result = NULL; + } + return(count); } +int +sudo_ldap_display_cmnd(nss, pw) + struct sudo_nss *nss; + struct passwd *pw; +{ + LDAP *ld = (LDAP *) nss->handle; + LDAPMessage *entry = NULL, *result = NULL; /* used for searches */ + char *filt; /* used to parse attributes */ + int rc, found, do_netgr; /* temp/final return values */ + + if (ld == NULL) + return(1); + + /* + * Okay - time to search for anything that matches this user + * Lets limit it to only two queries of the LDAP server + * + * The first pass will look by the username, groups, and + * the keyword ALL. We will then inspect the results that + * came back from the query. We don't need to inspect the + * sudoUser in this pass since the LDAP server already scanned + * it for us. + * + * The second pass will return all the entries that contain + * user netgroups. Then we take the netgroups returned and + * try to match them against the username. + */ + for (found = FALSE, do_netgr = 0; !found && do_netgr < 2; do_netgr++) { + 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); + efree(filt); + if (rc != LDAP_SUCCESS) + continue; /* no entries for this pass */ + + LDAP_FOREACH(entry, ld, result) { + if ((!do_netgr || + sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) && + sudo_ldap_check_host(ld, entry) && + sudo_ldap_check_command(ld, entry, NULL) && + sudo_ldap_check_runas(ld, entry)) { + + found = TRUE; + break; + } + } + ldap_msgfree(result); + result = NULL; + } + + if (found) + printf("%s%s%s\n", safe_cmnd ? safe_cmnd : user_cmnd, + user_args ? " " : "", user_args ? user_args : ""); + return(!found); +} + +#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S +static int +sudo_ldap_sasl_interact(ld, flags, _auth_id, _interact) + LDAP *ld; + unsigned int flags; + void *_auth_id; + void *_interact; +{ + char *auth_id = (char *)_auth_id; + sasl_interact_t *interact = (sasl_interact_t *)_interact; + + for (; interact->id != SASL_CB_LIST_END; interact++) { + if (interact->id != SASL_CB_USER) + return(LDAP_PARAM_ERROR); + + if (auth_id != NULL) + interact->result = auth_id; + else if (interact->defresult != NULL) + interact->result = interact->defresult; + else + interact->result = ""; + + interact->len = strlen(interact->result); +#if SASL_VERSION_MAJOR < 2 + interact->result = estrdup(interact->result); +#endif /* SASL_VERSION_MAJOR < 2 */ + } + return(LDAP_SUCCESS); +} +#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */ + /* * Set LDAP options based on the config table. */ @@ -996,7 +1502,7 @@ sudo_ldap_set_options(ld) if (ival >= 0) { rc = ldap_set_option(conn, cur->opt_val, &ival); if (rc != LDAP_OPT_SUCCESS) { - warnx("ldap_set_option: %s -> %d: %s", + warningx("ldap_set_option: %s -> %d: %s", cur->conf_str, ival, ldap_err2string(rc)); return(-1); } @@ -1008,7 +1514,7 @@ sudo_ldap_set_options(ld) if (sval != NULL) { rc = ldap_set_option(conn, cur->opt_val, sval); if (rc != LDAP_OPT_SUCCESS) { - warnx("ldap_set_option: %s -> %s: %s", + warningx("ldap_set_option: %s -> %s: %s", cur->conf_str, sval, ldap_err2string(rc)); return(-1); } @@ -1026,7 +1532,7 @@ sudo_ldap_set_options(ld) tv.tv_usec = 0; rc = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv); if (rc != LDAP_OPT_SUCCESS) { - warnx("ldap_set_option(NETWORK_TIMEOUT, %ld): %s", + warningx("ldap_set_option(NETWORK_TIMEOUT, %ld): %s", (long)tv.tv_sec, ldap_err2string(rc)); return(-1); } @@ -1040,7 +1546,7 @@ sudo_ldap_set_options(ld) int val = LDAP_OPT_X_TLS_HARD; rc = ldap_set_option(ld, LDAP_OPT_X_TLS, &val); if (rc != LDAP_SUCCESS) { - warnx("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD): %s", + warningx("ldap_set_option(LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_HARD): %s", ldap_err2string(rc)); return(-1); } @@ -1051,16 +1557,102 @@ sudo_ldap_set_options(ld) } /* - * Open a connection to the LDAP server. + * Connect to the LDAP server specified by ld */ -static LDAP * -sudo_ldap_open() +static int +sudo_ldap_bind_s(ld) + LDAP *ld; { - LDAP *ld = NULL; int rc; + const char *old_ccname = user_ccname; +#ifdef HAVE_GSS_KRB5_CCACHE_NAME + unsigned int status; +#endif + +#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S + if (ldap_conf.rootuse_sasl == TRUE || + (ldap_conf.rootuse_sasl != FALSE && ldap_conf.use_sasl == TRUE)) { + void *auth_id = ldap_conf.rootsasl_auth_id ? + ldap_conf.rootsasl_auth_id : ldap_conf.sasl_auth_id; + + if (ldap_conf.krb5_ccname != NULL) { +#ifdef HAVE_GSS_KRB5_CCACHE_NAME + if (gss_krb5_ccache_name(&status, ldap_conf.krb5_ccname, &old_ccname) + != GSS_S_COMPLETE) { + old_ccname = NULL; + DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1); + } +#else + sudo_setenv("KRB5CCNAME", ldap_conf.krb5_ccname, TRUE); +#endif + } + rc = ldap_sasl_interactive_bind_s(ld, ldap_conf.binddn, "GSSAPI", + NULL, NULL, LDAP_SASL_QUIET, sudo_ldap_sasl_interact, auth_id); + if (ldap_conf.krb5_ccname != NULL) { +#ifdef HAVE_GSS_KRB5_CCACHE_NAME + if (gss_krb5_ccache_name(&status, old_ccname, NULL) != GSS_S_COMPLETE) + DPRINTF(("gss_krb5_ccache_name() failed: %d", status), 1); +#else + if (old_ccname != NULL) + sudo_setenv("KRB5CCNAME", old_ccname, TRUE); + else + sudo_unsetenv("KRB5CCNAME"); +#endif + } + if (rc != LDAP_SUCCESS) { + warningx("ldap_sasl_interactive_bind_s(): %s", ldap_err2string(rc)); + return(-1); + } + DPRINTF(("ldap_sasl_interactive_bind_s() ok"), 1); + } else +#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */ +#ifdef HAVE_LDAP_SASL_BIND_S + { + struct berval bv; + + bv.bv_val = ldap_conf.bindpw ? ldap_conf.bindpw : ""; + bv.bv_len = strlen(bv.bv_val); + + rc = ldap_sasl_bind_s(ld, ldap_conf.binddn, LDAP_SASL_SIMPLE, &bv, + NULL, NULL, NULL); + if (rc != LDAP_SUCCESS) { + warningx("ldap_sasl_bind_s(): %s", ldap_err2string(rc)); + return(-1); + } + DPRINTF(("ldap_sasl_bind_s() ok"), 1); + } +#else + { + rc = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw); + if (rc != LDAP_SUCCESS) { + warningx("ldap_simple_bind_s(): %s", ldap_err2string(rc)); + return(-1); + } + DPRINTF(("ldap_simple_bind_s() ok"), 1); + } +#endif + return(0); +} + +/* + * Open a connection to the LDAP server. + * Returns 0 on success and non-zero on failure. + */ +int +sudo_ldap_open(nss) + struct sudo_nss *nss; +{ + LDAP *ld; + int rc, ldapnoinit = FALSE; if (!sudo_ldap_read_config()) - return(NULL); + return(-1); + + /* Prevent reading of user ldaprc and system defaults. */ + if (getenv("LDAPNOINIT") == NULL) { + ldapnoinit = TRUE; + sudo_setenv("LDAPNOINIT", "1", TRUE); + } /* Connect to LDAP server */ #ifdef HAVE_LDAP_INITIALIZE @@ -1068,51 +1660,55 @@ sudo_ldap_open() DPRINTF(("ldap_initialize(ld, %s)", ldap_conf.uri), 2); rc = ldap_initialize(&ld, ldap_conf.uri); } else -#endif /* HAVE_LDAP_INITIALIZE */ +#endif rc = sudo_ldap_init(&ld, ldap_conf.host, ldap_conf.port); if (rc != LDAP_SUCCESS) { - warnx("unable to initialize LDAP: %s", ldap_err2string(rc)); - return(NULL); + warningx("unable to initialize LDAP: %s", ldap_err2string(rc)); + return(-1); } + if (ldapnoinit) + sudo_unsetenv("LDAPNOINIT"); + /* Set LDAP options */ if (sudo_ldap_set_options(ld) < 0) - return(NULL); + return(-1); if (ldap_conf.ssl_mode == SUDO_LDAP_STARTTLS) { #ifdef HAVE_LDAP_START_TLS_S rc = ldap_start_tls_s(ld, NULL, NULL); if (rc != LDAP_SUCCESS) { - warnx("ldap_start_tls_s(): %s", ldap_err2string(rc)); - ldap_unbind(ld); - return(NULL); + warningx("ldap_start_tls_s(): %s", ldap_err2string(rc)); + return(-1); } DPRINTF(("ldap_start_tls_s() ok"), 1); #else - warnx("start_tls specified but LDAP libs do not support ldap_start_tls_s()"); + warningx("start_tls specified but LDAP libs do not support ldap_start_tls_s()"); #endif /* HAVE_LDAP_START_TLS_S */ } /* Actually connect */ - if ((rc = ldap_simple_bind_s(ld, ldap_conf.binddn, ldap_conf.bindpw))) { - warnx("ldap_simple_bind_s: %s", ldap_err2string(rc)); - return(NULL); - } - DPRINTF(("ldap_simple_bind_s() ok"), 1); + if (sudo_ldap_bind_s(ld) != 0) + return(-1); - return(ld); + nss->handle = ld; + return(0); } -static void -sudo_ldap_update_defaults(ld) - LDAP *ld; +int +sudo_ldap_setdefs(nss) + struct sudo_nss *nss; { + LDAP *ld = (LDAP *) nss->handle; LDAPMessage *entry = NULL, *result = NULL; /* used for searches */ int rc; /* temp return value */ - rc = ldap_search_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, - "cn=defaults", NULL, 0, &result); - if (rc == LDAP_SUCCESS && (entry = ldap_first_entry(ld, result))) { + if (ld == NULL) + return(-1); + + rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, + "cn=defaults", NULL, 0, NULL, NULL, NULL, -1, &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); } else @@ -1120,28 +1716,89 @@ sudo_ldap_update_defaults(ld) if (result) ldap_msgfree(result); + + return(0); } /* * like sudoers_lookup() - only LDAP style */ int -sudo_ldap_check(pwflag) +sudo_ldap_lookup(nss, ret, pwflag) + struct sudo_nss *nss; + int ret; int pwflag; { - LDAP *ld; - LDAPMessage *entry = NULL, *result = NULL; /* used for searches */ - char *filt; /* used to parse attributes */ - int rc, ret = FALSE, do_netgr; /* temp/final return values */ + LDAP *ld = (LDAP *) nss->handle; + LDAPMessage *entry = NULL, *result = NULL; + char *filt; + int do_netgr, rc, matched; int setenv_implied; - int ldap_user_matches = FALSE, ldap_host_matches = FALSE; /* flags */ + int ldap_user_matches = FALSE, ldap_host_matches = FALSE; + struct passwd *pw = list_pw ? list_pw : sudo_user.pw; + + if (ld == NULL) + return(ret); - /* Open a connection to the LDAP server. */ - if ((ld = sudo_ldap_open()) == NULL) - return(VALIDATE_ERROR); + if (pwflag) { + int doauth = UNSPEC; + enum def_tupple pwcheck = + (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple; + + 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); + efree(filt); + if (rc != LDAP_SUCCESS) + continue; + + LDAP_FOREACH(entry, ld, result) { + /* only verify netgroup matches in pass 2 */ + if (do_netgr && !sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) + continue; - /* Parse Default options. */ - sudo_ldap_update_defaults(ld); + ldap_user_matches = TRUE; + if (sudo_ldap_check_host(ld, entry)) { + ldap_host_matches = TRUE; + if ((pwcheck == any && doauth != FALSE) || + (pwcheck == all && doauth == FALSE)) + doauth = sudo_ldap_check_bool(ld, entry, "authenticate"); + /* Only check the command when listing another user. */ + if (user_uid == 0 || list_pw == NULL || + user_uid == list_pw->pw_uid || + sudo_ldap_check_command(ld, entry, NULL)) { + matched = 1; + break; /* end foreach */ + } + } + } + ldap_msgfree(result); + result = NULL; + } + if (matched || user_uid == 0) { + SET(ret, VALIDATE_OK); + CLR(ret, VALIDATE_NOT_OK); + if (def_authenticate) { + switch (pwcheck) { + case always: + SET(ret, FLAG_CHECK_USER); + break; + case all: + case any: + if (doauth == FALSE) + def_authenticate = FALSE; + break; + case never: + def_authenticate = FALSE; + break; + default: + break; + } + } + } + goto done; + } /* * Okay - time to search for anything that matches this user @@ -1158,112 +1815,78 @@ sudo_ldap_check(pwflag) * try to match them against the username. */ setenv_implied = FALSE; - for (do_netgr = 0; !ret && do_netgr < 2; do_netgr++) { - filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(); + for (matched = 0, do_netgr = 0; !matched && do_netgr < 2; do_netgr++) { + filt = do_netgr ? estrdup("sudoUser=+*") : sudo_ldap_build_pass1(pw); DPRINTF(("ldap search '%s'", filt), 1); - rc = ldap_search_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt, - NULL, 0, &result); + rc = ldap_search_ext_s(ld, ldap_conf.base, LDAP_SCOPE_SUBTREE, filt, + NULL, 0, NULL, NULL, NULL, -1, &result); if (rc != LDAP_SUCCESS) DPRINTF(("nothing found for '%s'", filt), 1); efree(filt); /* parse each entry returned from this most recent search */ - entry = rc ? NULL : ldap_first_entry(ld, result); - while (entry != NULL) { - DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1); - if ( - /* first verify user netgroup matches - only if in pass 2 */ - (!do_netgr || sudo_ldap_check_user_netgroup(ld, entry)) && - /* remember that user matched */ - (ldap_user_matches = -1) && - /* verify host match */ - sudo_ldap_check_host(ld, entry) && - /* remember that host matched */ - (ldap_host_matches = -1) && - /* add matches for listing later */ - sudo_ldap_add_match(ld, entry, pwflag) && - /* verify command match */ - sudo_ldap_check_command(ld, entry, &setenv_implied) && - /* verify runas match */ - sudo_ldap_check_runas(ld, entry) - ) { - /* We have a match! */ - DPRINTF(("Perfect Matched!"), 1); - /* pick up any options */ - if (setenv_implied) - def_setenv = TRUE; - sudo_ldap_parse_options(ld, entry); + if (rc == LDAP_SUCCESS) { + LDAP_FOREACH(entry, ld, result) { + DPRINTF(("found:%s", ldap_get_dn(ld, entry)), 1); + if ( + /* first verify user netgroup matches - only if in pass 2 */ + (!do_netgr || sudo_ldap_check_user_netgroup(ld, entry, pw->pw_name)) && + /* remember that user matched */ + (ldap_user_matches = TRUE) && + /* verify host match */ + sudo_ldap_check_host(ld, entry) && + /* remember that host matched */ + (ldap_host_matches = TRUE) && + /* verify runas match */ + sudo_ldap_check_runas(ld, entry) && + /* verify command match */ + (rc = sudo_ldap_check_command(ld, entry, &setenv_implied)) != UNSPEC + ) { + /* We have a match! */ + DPRINTF(("Command %sallowed", rc == TRUE ? "" : "NOT "), 1); + matched = TRUE; + if (rc == TRUE) { + /* pick up any options */ + if (setenv_implied) + def_setenv = TRUE; + sudo_ldap_parse_options(ld, entry); #ifdef HAVE_SELINUX - /* Set role and type if not specified on command line. */ - if (user_role == NULL) - user_role = def_role; - if (user_type == NULL) - user_type = def_type; + /* Set role and type if not specified on command line. */ + if (user_role == NULL) + user_role = def_role; + if (user_type == NULL) + user_type = def_type; #endif /* HAVE_SELINUX */ - /* make sure we don't reenter loop */ - ret = VALIDATE_OK; - /* break from inside for loop */ - break; + /* make sure we don't reenter loop */ + SET(ret, VALIDATE_OK); + CLR(ret, VALIDATE_NOT_OK); + } else { + SET(ret, VALIDATE_NOT_OK); + CLR(ret, VALIDATE_OK); + } + /* break from inside for loop */ + break; + } } - entry = ldap_next_entry(ld, entry); - } - if (result) ldap_msgfree(result); - result = NULL; + result = NULL; + } } - sudo_ldap_close(ld); /* shut down connection */ - +done: DPRINTF(("user_matches=%d", ldap_user_matches), 1); DPRINTF(("host_matches=%d", ldap_host_matches), 1); - /* Check for special case for -v, -k, -l options */ - if (pwflag && ldap_user_matches && ldap_host_matches) { - /* - * Handle verifypw & listpw - * - * To be extra paranoid, since we haven't read any NOPASSWD options - * in /etc/sudoers yet, but we have to make the decission now, lets - * assume the worst and prefer to prompt for password unless the setting - * is "never". (example verifypw=never or listpw=never) - * - */ - ret = VALIDATE_OK; - if (pwflag == -1) { - SET(ret, FLAG_NOPASS); /* -k or -K */ - } else { - switch (sudo_defs_table[pwflag].sd_un.tuple) { - case never: - SET(ret, FLAG_NOPASS); - break; - case always: - if (def_authenticate) - SET(ret, FLAG_CHECK_USER); - break; - default: - break; - } - } - } - if (ISSET(ret, VALIDATE_OK)) { - /* we have a match, should we check the password? */ - if (!def_authenticate) - SET(ret, FLAG_NOPASS); - if (def_noexec) - SET(ret, FLAG_NOEXEC); - if (def_setenv) - SET(ret, FLAG_SETENV); - } else { + if (!ISSET(ret, VALIDATE_OK)) { /* we do not have a match */ - ret = VALIDATE_NOT_OK; - if (pwflag) + if (pwflag && list_pw == NULL) SET(ret, FLAG_NO_CHECK); - else if (!ldap_user_matches) - SET(ret, FLAG_NO_USER); - else if (!ldap_host_matches) - SET(ret, FLAG_NO_HOST); } - DPRINTF(("sudo_ldap_check(%d)=0x%02x", pwflag, ret), 1); + if (ldap_user_matches) + CLR(ret, FLAG_NO_USER); + if (ldap_host_matches) + CLR(ret, FLAG_NO_HOST); + DPRINTF(("sudo_ldap_lookup(%d)=0x%02x", pwflag, ret), 1); return(ret); } @@ -1271,9 +1894,23 @@ sudo_ldap_check(pwflag) /* * shut down LDAP connection */ -static void -sudo_ldap_close(LDAP *ld) +int +sudo_ldap_close(nss) + struct sudo_nss *nss; { - if (ld) - ldap_unbind_s(ld); + if (nss->handle != NULL) { + ldap_unbind_ext_s((LDAP *) nss->handle, NULL, NULL); + nss->handle = NULL; + } + return(0); +} + +/* + * STUB + */ +int +sudo_ldap_parse(nss) + struct sudo_nss *nss; +{ + return(0); } diff --git a/lex.yy.c b/lex.yy.c deleted file mode 100644 index b05dd92..0000000 --- a/lex.yy.c +++ /dev/null @@ -1,3281 +0,0 @@ -/* $OpenBSD: flex.skl,v 1.10 2007/01/26 14:38:19 tsi Exp $ */ - -/* A lexical scanner generated by flex */ - -/* Scanner skeleton version: - * $Header: /home/cvs/courtesan/sudo/Attic/lex.yy.c,v 1.46.2.11 2008/06/26 11:53:49 millert Exp $ - */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 - -#include -#include - - -/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ -#ifdef c_plusplus -#ifndef __cplusplus -#define __cplusplus -#endif -#endif - - -#ifdef __cplusplus - -#include -#include - -/* Use prototypes in function declarations. */ -#define YY_USE_PROTOS - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -#ifdef __STDC__ - -#define YY_USE_PROTOS -#define YY_USE_CONST - -#endif /* __STDC__ */ -#endif /* ! __cplusplus */ - -#ifdef __TURBOC__ - #pragma warn -rch - #pragma warn -use -#include -#include -#define YY_USE_CONST -#define YY_USE_PROTOS -#endif - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - - -#ifdef YY_USE_PROTOS -#define YY_PROTO(proto) proto -#else -#define YY_PROTO(proto) () -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN yy_start = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START ((yy_start - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart( yyin ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#define YY_BUF_SIZE 16384 - -typedef struct yy_buffer_state *YY_BUFFER_STATE; - -extern int yyleng; -extern FILE *yyin, *yyout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - -/* The funky do-while in the following #define is used to turn the definition - * int a single C statement (which needs a semi-colon terminator). This - * avoids problems with code like: - * - * if ( condition_holds ) - * yyless( 5 ); - * else - * do_something_else(); - * - * Prior to using the do-while the compiler would get upset at the - * "else" because it interpreted the "if" statement as being all - * done when it reached the ';' after the yyless() call. - */ - -/* Return all but the first 'n' matched characters back to the input stream. */ - -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - *yy_cp = yy_hold_char; \ - YY_RESTORE_YY_MORE_OFFSET \ - yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, yytext_ptr ) - -/* The following is because we cannot portably get our hands on size_t - * (without autoconf's help, which isn't available because we want - * flex-generated scanners to compile on their own). - */ -typedef unsigned int yy_size_t; - - -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via yyrestart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - }; - -static YY_BUFFER_STATE yy_current_buffer = 0; - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - */ -#define YY_CURRENT_BUFFER yy_current_buffer - - -/* yy_hold_char holds the character lost when yytext is formed. */ -static char yy_hold_char; - -static int yy_n_chars; /* number of characters read into yy_ch_buf */ - - -int yyleng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = (char *) 0; -static int yy_init = 1; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow yywrap()'s to do buffer switches - * instead of setting up a fresh yyin. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void yyrestart YY_PROTO(( FILE *input_file )); - -void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); -void yy_load_buffer_state YY_PROTO(( void )); -YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); -void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); -void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); -void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); -#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) - -YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); -YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); -YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); - -static void *yy_flex_alloc YY_PROTO(( yy_size_t )); -static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); -static void yy_flex_free YY_PROTO(( void * )); - -#define yy_new_buffer yy_create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) - -typedef unsigned char YY_CHAR; -FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; -typedef int yy_state_type; -extern char *yytext; -#define yytext_ptr yytext - -static yy_state_type yy_get_previous_state YY_PROTO(( void )); -static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); -static int yy_get_next_buffer YY_PROTO(( void )); -static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - yytext_ptr = yy_bp; \ - yyleng = (int) (yy_cp - yy_bp); \ - yy_hold_char = *yy_cp; \ - *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[610] = - { 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 49, 38, 44, 43, 42, 47, - 38, 31, 47, 38, 39, 38, 38, 38, 38, 41, - 40, 32, 32, 32, 32, 32, 32, 47, 38, 38, - 32, 32, 32, 32, 32, 33, 47, 33, 35, 33, - 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, - 47, 33, 33, 1, 16, 15, 16, 15, 15, 47, - 47, 2, 8, 7, 8, 3, 8, 4, 47, 12, - 12, 12, 10, 11, 38, 0, 44, 42, 0, 46, - 26, 0, 25, 0, 37, 37, 0, 38, 38, 0, - - 38, 38, 38, 38, 0, 29, 32, 32, 32, 32, - 32, 32, 38, 45, 38, 38, 38, 38, 38, 38, - 33, 0, 0, 33, 26, 0, 25, 0, 33, 0, - 33, 33, 33, 33, 33, 33, 32, 32, 32, 32, - 32, 32, 33, 33, 1, 16, 16, 14, 13, 14, - 0, 2, 8, 0, 5, 6, 8, 8, 12, 0, - 12, 12, 0, 9, 0, 38, 38, 38, 38, 38, - 0, 0, 29, 29, 32, 32, 32, 32, 32, 32, - 32, 38, 38, 38, 38, 38, 38, 0, 34, 33, - 33, 33, 33, 33, 32, 32, 32, 32, 32, 32, - - 32, 33, 9, 38, 38, 38, 38, 38, 38, 0, - 30, 30, 30, 0, 0, 29, 29, 29, 29, 29, - 29, 29, 32, 32, 32, 32, 32, 32, 32, 38, - 38, 38, 38, 33, 33, 33, 33, 33, 33, 32, - 32, 32, 32, 32, 32, 32, 33, 38, 38, 38, - 0, 0, 30, 30, 30, 0, 29, 29, 0, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 0, 22, 32, 32, 32, 32, 32, 38, 38, 38, - 33, 33, 33, 32, 32, 32, 32, 32, 33, 38, - 38, 38, 38, 38, 0, 30, 0, 29, 29, 29, - - 0, 0, 0, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 32, 32, 32, 32, - 32, 38, 38, 38, 33, 33, 33, 33, 33, 32, - 32, 32, 32, 32, 33, 27, 27, 27, 0, 0, - 29, 29, 29, 29, 29, 29, 29, 0, 0, 0, - 0, 0, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 0, 21, 32, 32, - 0, 20, 0, 23, 38, 38, 38, 27, 27, 27, - 32, 32, 33, 38, 27, 27, 27, 27, 0, 29, - 0, 29, 29, 29, 29, 29, 29, 29, 29, 29, - - 29, 29, 0, 0, 0, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 32, 32, - 36, 38, 17, 33, 27, 27, 27, 27, 32, 32, - 33, 38, 28, 28, 28, 29, 0, 0, 0, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 0, 0, 0, 0, 0, 29, 29, 29, - 29, 29, 29, 29, 29, 0, 19, 0, 24, 38, - 17, 33, 28, 28, 28, 38, 38, 28, 28, 28, - 28, 28, 0, 0, 0, 0, 0, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - - 29, 29, 29, 29, 29, 29, 29, 18, 33, 33, - 28, 28, 28, 28, 28, 38, 38, 38, 28, 28, - 0, 0, 0, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 33, 33, 33, 28, 28, 38, 38, 38, 38, - 38, 0, 0, 0, 0, 0, 29, 29, 29, 29, - 29, 29, 29, 29, 33, 33, 33, 33, 33, 38, - 38, 38, 29, 29, 29, 29, 29, 29, 33, 33, - 33, 38, 38, 38, 38, 38, 29, 29, 29, 29, - 29, 33, 33, 33, 33, 33, 27, 27, 27, 27, - - 27, 27, 27, 27, 27, 27, 27, 27, 0 - } ; - -static yyconst int yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 4, 5, 6, 1, 7, 1, 1, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 22, 22, 23, 24, 1, 1, - 25, 26, 10, 26, 27, 28, 29, 30, 31, 28, - 32, 33, 32, 32, 32, 32, 32, 34, 35, 36, - 32, 37, 38, 39, 40, 41, 42, 43, 32, 32, - 10, 44, 10, 1, 45, 1, 46, 47, 47, 48, - - 49, 50, 51, 51, 52, 51, 51, 53, 54, 55, - 56, 51, 51, 57, 58, 59, 60, 51, 51, 51, - 51, 51, 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, 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, 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, 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, - 1, 1, 1, 1, 1 - } ; - -static yyconst int yy_meta[61] = - { 0, - 1, 2, 3, 4, 5, 6, 1, 4, 4, 1, - 1, 2, 7, 8, 9, 10, 10, 10, 10, 10, - 10, 10, 10, 11, 6, 4, 12, 12, 12, 12, - 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 13, 14, 15, 15, 15, 15, 15, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 - } ; - -static yyconst short int yy_base[681] = - { 0, - 0, 32, 72, 0, 62, 131, 132, 139, 182, 241, - 300, 343, 145, 150, 3097, 3052, 3093, 3790, 3068, 3059, - 3008, 3790, 3790, 2996, 3790, 161, 374, 179, 161, 3015, - 3790, 424, 2995, 469, 3002, 3009, 2982, 518, 190, 102, - 2949, 2944, 2927, 2913, 2905, 2909, 201, 2873, 3790, 2864, - 306, 531, 232, 240, 581, 2855, 626, 2855, 2852, 2838, - 675, 248, 114, 2847, 0, 3790, 2844, 0, 3790, 314, - 64, 0, 2803, 3790, 115, 3790, 146, 3790, 158, 2802, - 171, 275, 3790, 270, 2801, 355, 2836, 2818, 2808, 3790, - 2757, 684, 2739, 709, 325, 2729, 718, 355, 729, 2739, - - 2739, 390, 485, 493, 2675, 151, 764, 0, 2665, 245, - 2657, 2649, 338, 3790, 124, 148, 232, 219, 287, 278, - 2633, 794, 2656, 0, 2605, 819, 2593, 828, 530, 853, - 549, 864, 2622, 642, 745, 650, 899, 0, 2604, 292, - 2596, 2571, 382, 230, 2566, 0, 2548, 305, 3790, 3790, - 333, 0, 2507, 700, 3790, 3790, 2505, 492, 2489, 2527, - 384, 339, 350, 2529, 844, 936, 880, 720, 967, 2484, - 2460, 1002, 201, 1038, 1073, 2454, 2433, 2438, 2431, 2409, - 2403, 265, 236, 2369, 356, 147, 370, 2411, 3790, 1110, - 915, 753, 1141, 2399, 1176, 2354, 2315, 2302, 2283, 2275, - - 2281, 479, 2293, 947, 375, 0, 0, 343, 392, 2270, - 2236, 955, 515, 2222, 2221, 513, 983, 1213, 1018, 854, - 1249, 1056, 2214, 539, 2196, 2186, 2153, 2149, 2125, 540, - 388, 764, 529, 1090, 532, 0, 0, 427, 661, 2133, - 583, 2110, 2101, 2084, 2080, 2087, 645, 1121, 1159, 1194, - 2095, 2080, 1129, 2080, 2033, 2032, 2021, 667, 1229, 683, - 1265, 775, 1286, 0, 1304, 1323, 1339, 888, 1359, 1377, - 729, 3790, 2009, 1999, 1972, 1972, 1948, 481, 513, 651, - 1396, 1406, 1416, 1959, 1919, 1925, 1925, 1913, 675, 1424, - 791, 1434, 1444, 1455, 1926, 1873, 1856, 1819, 1484, 792, - - 1811, 1810, 1463, 802, 824, 827, 1471, 852, 1521, 0, - 1502, 1558, 1537, 923, 1594, 1576, 730, 1745, 1737, 958, - 1040, 19, 805, 670, 1610, 819, 1639, 1649, 1631, 1081, - 1711, 1718, 1112, 1251, 318, 1661, 1669, 991, 1694, 1677, - 1615, 1677, 1692, 1708, 1273, 1727, 1745, 1762, 1624, 1621, - 1620, 1772, 1056, 1101, 1387, 1622, 1778, 1788, 1799, 0, - 1817, 1836, 1788, 1347, 1872, 1854, 1324, 3790, 1590, 1578, - 1325, 3790, 1522, 3790, 984, 757, 771, 1908, 1888, 1545, - 1572, 1543, 1038, 1916, 636, 0, 0, 866, 1559, 1505, - 1924, 937, 1945, 1142, 1955, 0, 1966, 1977, 1993, 1716, - - 2012, 2030, 1496, 1482, 2049, 1150, 1185, 1934, 2040, 2057, - 2067, 2078, 0, 2096, 2115, 2067, 1896, 2133, 1523, 1837, - 1434, 879, 1194, 2150, 1377, 0, 0, 970, 1838, 1957, - 1426, 2181, 2158, 2166, 1028, 1407, 1390, 1389, 2191, 1306, - 1435, 1577, 2199, 1650, 2212, 0, 2223, 2234, 2250, 2001, - 2269, 2287, 2304, 1260, 1244, 1225, 2314, 1745, 1854, 2322, - 1084, 1103, 2333, 0, 2324, 1968, 3790, 2116, 3790, 1451, - 3790, 2343, 2351, 2359, 1167, 2372, 846, 2380, 2388, 2401, - 2409, 2419, 2422, 1172, 1153, 1101, 2432, 1057, 1039, 1693, - 2134, 2438, 2182, 2450, 0, 2461, 2472, 2488, 2258, 2507, - - 2525, 1032, 1012, 2543, 2287, 947, 1187, 880, 2553, 1483, - 2561, 2569, 2577, 2585, 2595, 2600, 2610, 2624, 2634, 2368, - 850, 833, 2644, 798, 780, 2235, 2473, 2652, 2526, 2662, - 0, 2673, 2684, 2700, 2496, 2721, 782, 740, 713, 2730, - 701, 2738, 2748, 2758, 2768, 2692, 2776, 1484, 2786, 2796, - 2807, 2813, 689, 638, 592, 2823, 566, 559, 2601, 550, - 416, 2836, 0, 1232, 2844, 1659, 2854, 2864, 2875, 2883, - 2893, 2904, 2912, 2920, 2928, 393, 0, 346, 2938, 2948, - 2958, 2968, 2146, 2978, 2988, 2998, 3790, 3004, 3012, 2708, - 3790, 3027, 2179, 3037, 3047, 3057, 3063, 3071, 3100, 3108, - - 3116, 3145, 293, 3153, 3137, 123, 3182, 3166, 3790, 3226, - 3241, 3256, 3271, 3286, 3301, 3316, 3331, 3346, 3352, 3367, - 3382, 3397, 3412, 3427, 3442, 1242, 3457, 3472, 3487, 3502, - 3508, 3515, 3530, 1593, 3536, 3543, 3549, 3555, 3561, 3568, - 3574, 3580, 3586, 3593, 3601, 3607, 3613, 3619, 1211, 1321, - 3626, 3634, 3640, 3646, 3653, 3661, 3667, 3675, 1694, 1762, - 3682, 3690, 1834, 1871, 3696, 3704, 3711, 3719, 3725, 3733, - 1302, 1375, 3740, 1888, 1943, 3746, 3754, 3760, 3768, 3774 - } ; - -static yyconst short int yy_def[681] = - { 0, - 609, 1, 609, 3, 1, 1, 610, 610, 611, 611, - 612, 612, 613, 613, 609, 614, 609, 609, 609, 615, - 616, 609, 609, 617, 609, 618, 614, 27, 27, 619, - 609, 609, 32, 32, 34, 34, 34, 614, 27, 614, - 32, 32, 34, 34, 34, 620, 621, 622, 609, 623, - 624, 620, 52, 52, 609, 55, 55, 57, 57, 57, - 620, 52, 620, 609, 625, 609, 625, 625, 609, 609, - 609, 626, 627, 609, 627, 609, 627, 609, 628, 629, - 629, 629, 609, 609, 614, 614, 609, 609, 615, 609, - 616, 616, 617, 617, 618, 630, 614, 614, 27, 619, - - 99, 99, 99, 99, 631, 632, 32, 34, 34, 34, - 34, 34, 614, 609, 614, 614, 99, 614, 614, 614, - 620, 620, 633, 634, 622, 622, 623, 623, 624, 620, - 620, 52, 132, 132, 132, 132, 55, 57, 57, 57, - 57, 57, 620, 620, 609, 625, 625, 609, 609, 609, - 609, 626, 627, 627, 609, 609, 627, 627, 629, 609, - 629, 629, 609, 609, 609, 614, 166, 166, 99, 169, - 635, 609, 636, 609, 32, 34, 34, 34, 34, 34, - 34, 614, 614, 169, 614, 614, 614, 633, 609, 620, - 190, 190, 132, 193, 55, 57, 57, 57, 57, 57, - - 57, 620, 609, 614, 614, 166, 166, 166, 614, 637, - 638, 638, 212, 639, 638, 640, 174, 609, 218, 218, - 609, 218, 34, 34, 34, 34, 34, 34, 34, 614, - 614, 614, 614, 620, 620, 190, 190, 190, 620, 57, - 57, 57, 57, 57, 57, 57, 620, 166, 166, 166, - 609, 641, 641, 253, 641, 642, 643, 644, 609, 645, - 221, 645, 609, 263, 645, 609, 266, 266, 609, 266, - 609, 609, 34, 34, 34, 34, 34, 614, 614, 614, - 190, 190, 190, 57, 57, 57, 57, 57, 620, 614, - 614, 166, 166, 614, 646, 646, 647, 648, 609, 609, - - 649, 650, 609, 651, 651, 652, 269, 652, 609, 309, - 652, 609, 312, 312, 609, 312, 34, 34, 34, 34, - 34, 614, 614, 614, 620, 620, 190, 190, 620, 57, - 57, 57, 57, 57, 620, 614, 336, 336, 609, 653, - 654, 299, 609, 343, 343, 609, 343, 609, 609, 649, - 649, 609, 609, 655, 655, 656, 315, 656, 609, 359, - 656, 609, 362, 362, 609, 362, 609, 609, 34, 34, - 609, 609, 609, 609, 614, 614, 614, 620, 378, 378, - 57, 57, 620, 614, 614, 336, 336, 336, 609, 657, - 609, 658, 346, 658, 658, 395, 658, 609, 398, 398, - - 609, 398, 659, 660, 609, 609, 661, 661, 662, 365, - 662, 609, 412, 662, 609, 415, 415, 415, 34, 34, - 614, 614, 614, 620, 620, 378, 378, 378, 57, 57, - 620, 614, 432, 432, 432, 609, 663, 664, 609, 665, - 665, 666, 401, 666, 666, 445, 666, 609, 448, 448, - 609, 448, 609, 609, 659, 659, 609, 609, 667, 667, - 668, 668, 668, 463, 668, 609, 609, 609, 609, 614, - 609, 620, 472, 472, 472, 614, 614, 432, 432, 432, - 432, 614, 609, 609, 663, 663, 609, 609, 669, 669, - 670, 451, 670, 670, 494, 670, 609, 497, 497, 609, - - 497, 671, 672, 609, 609, 673, 673, 614, 472, 620, - 472, 472, 472, 472, 620, 432, 432, 432, 432, 614, - 674, 675, 609, 609, 676, 676, 677, 500, 677, 677, - 530, 677, 609, 533, 533, 533, 609, 671, 671, 609, - 609, 472, 472, 472, 472, 620, 614, 614, 432, 432, - 614, 609, 609, 674, 674, 609, 609, 678, 678, 679, - 679, 679, 562, 562, 620, 620, 472, 472, 620, 432, - 432, 432, 609, 609, 609, 609, 680, 680, 472, 472, - 472, 432, 614, 432, 432, 614, 609, 609, 609, 609, - 609, 472, 620, 472, 472, 620, 614, 614, 614, 620, - - 620, 620, 614, 614, 614, 620, 620, 620, 0, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609 - } ; - -static yyconst short int yy_nxt[3851] = - { 0, - 16, 17, 18, 19, 16, 20, 21, 22, 23, 16, - 24, 25, 16, 16, 26, 27, 28, 29, 27, 27, - 27, 27, 27, 30, 31, 23, 32, 32, 32, 32, - 33, 34, 34, 35, 34, 36, 34, 37, 34, 34, - 34, 34, 34, 38, 16, 39, 39, 39, 39, 39, - 16, 16, 16, 16, 16, 16, 16, 40, 16, 16, - 41, 42, 86, 64, 43, 151, 114, 23, 44, 23, - 375, 45, 46, 17, 18, 19, 46, 47, 48, 23, - 49, 46, 50, 25, 46, 46, 51, 52, 53, 54, - 52, 52, 52, 52, 52, 30, 31, 23, 55, 55, - - 55, 55, 56, 57, 57, 58, 57, 59, 57, 60, - 57, 57, 57, 57, 57, 61, 46, 62, 62, 62, - 62, 62, 46, 46, 46, 46, 46, 46, 46, 63, - 46, 46, 64, 17, 66, 67, 23, 68, 23, 155, - 17, 66, 67, 69, 68, 86, 81, 18, 82, 83, - 69, 81, 18, 82, 83, 69, 68, 122, 154, 158, - 114, 115, 69, 68, 96, 172, 122, 86, 96, 96, - 156, 182, 161, 144, 174, 70, 103, 103, 103, 103, - 103, 104, 70, 17, 18, 19, 96, 20, 84, 154, - 86, 86, 233, 84, 102, 102, 102, 102, 102, 102, - - 102, 102, 183, 85, 97, 101, 101, 101, 101, 101, - 101, 101, 101, 124, 160, 172, 124, 124, 124, 124, - 124, 124, 124, 124, 217, 71, 72, 72, 72, 72, - 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, - 72, 72, 17, 18, 19, 85, 20, 134, 134, 134, - 134, 134, 134, 134, 134, 135, 135, 135, 135, 135, - 136, 121, 86, 133, 133, 133, 133, 133, 133, 133, - 133, 163, 164, 122, 159, 177, 185, 202, 162, 86, - 178, 184, 179, 231, 71, 72, 72, 72, 72, 72, - 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, - - 72, 17, 18, 19, 74, 20, 151, 114, 86, 96, - 75, 76, 77, 96, 96, 148, 114, 149, 160, 150, - 230, 86, 197, 149, 78, 150, 187, 198, 96, 199, - 86, 96, 96, 96, 151, 114, 86, 150, 150, 151, - 114, 186, 162, 79, 17, 18, 19, 74, 20, 130, - 96, 163, 164, 75, 76, 77, 85, 150, 85, 391, - 85, 122, 85, 85, 85, 85, 85, 78, 97, 383, - 166, 167, 168, 166, 166, 166, 166, 166, 85, 85, - 85, 86, 160, 151, 114, 161, 79, 98, 204, 99, - 99, 99, 99, 99, 99, 99, 99, 100, 86, 86, - - 101, 101, 101, 101, 101, 170, 170, 170, 170, 170, - 170, 170, 170, 86, 231, 100, 528, 86, 86, 101, - 101, 101, 101, 101, 85, 122, 231, 160, 85, 609, - 85, 86, 279, 85, 85, 86, 85, 85, 85, 107, - 107, 107, 107, 107, 107, 107, 107, 100, 121, 121, - 107, 107, 107, 107, 107, 108, 108, 108, 108, 108, - 108, 108, 108, 108, 108, 108, 108, 86, 108, 101, - 101, 101, 101, 101, 85, 85, 85, 85, 85, 85, - 85, 85, 85, 85, 108, 108, 108, 108, 108, 108, - 108, 108, 609, 151, 114, 108, 108, 108, 108, 108, - - 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, - 170, 170, 170, 170, 85, 85, 85, 85, 85, 113, - 114, 85, 122, 85, 86, 85, 85, 172, 322, 85, - 255, 255, 255, 96, 247, 154, 217, 96, 96, 323, - 271, 85, 85, 85, 131, 234, 132, 132, 132, 132, - 132, 132, 132, 132, 100, 96, 86, 133, 133, 133, - 133, 133, 272, 391, 190, 191, 192, 190, 190, 190, - 190, 190, 86, 130, 122, 122, 133, 133, 133, 133, - 133, 121, 528, 86, 271, 121, 231, 121, 278, 492, - 121, 121, 122, 121, 121, 121, 137, 137, 137, 137, - - 137, 137, 137, 137, 100, 552, 272, 137, 137, 137, - 137, 137, 138, 138, 138, 138, 138, 138, 138, 138, - 138, 138, 138, 138, 122, 138, 133, 133, 133, 133, - 133, 121, 121, 121, 121, 121, 121, 121, 121, 121, - 121, 138, 138, 138, 138, 138, 138, 138, 138, 609, - 384, 552, 138, 138, 138, 138, 138, 194, 194, 194, - 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, - 194, 121, 121, 121, 121, 121, 143, 114, 121, 86, - 121, 172, 121, 121, 100, 91, 121, 91, 122, 91, - 217, 91, 91, 289, 86, 91, 259, 172, 121, 121, - - 121, 153, 552, 324, 122, 153, 261, 91, 91, 91, - 93, 153, 93, 86, 93, 172, 93, 93, 122, 95, - 93, 85, 335, 95, 153, 85, 85, 172, 377, 95, - 271, 367, 93, 93, 93, 207, 207, 207, 207, 207, - 208, 95, 95, 85, 169, 169, 169, 169, 169, 169, - 169, 169, 272, 368, 172, 169, 169, 169, 169, 169, - 194, 194, 194, 194, 194, 194, 194, 194, 237, 237, - 237, 237, 237, 238, 169, 169, 169, 169, 169, 175, - 175, 175, 175, 175, 175, 175, 175, 100, 609, 172, - 175, 175, 175, 175, 175, 121, 172, 121, 261, 121, - - 86, 121, 121, 492, 290, 121, 172, 86, 422, 169, - 169, 169, 169, 169, 86, 217, 172, 121, 121, 121, - 125, 443, 125, 280, 125, 261, 125, 125, 423, 127, - 125, 127, 325, 127, 86, 127, 127, 259, 172, 127, - 259, 172, 125, 125, 125, 96, 552, 261, 86, 96, - 307, 127, 127, 127, 129, 96, 121, 376, 129, 476, - 121, 121, 122, 552, 129, 609, 172, 96, 96, 264, - 264, 264, 264, 264, 265, 307, 129, 129, 121, 193, - 193, 193, 193, 193, 193, 193, 193, 85, 85, 86, - 193, 193, 193, 193, 193, 206, 206, 206, 206, 206, - - 206, 206, 206, 310, 310, 310, 310, 310, 311, 193, - 193, 193, 193, 193, 195, 195, 195, 195, 195, 195, - 195, 195, 86, 86, 470, 195, 195, 195, 195, 195, - 236, 236, 236, 236, 236, 236, 236, 236, 360, 360, - 360, 360, 360, 361, 193, 193, 193, 193, 193, 204, - 391, 205, 205, 205, 205, 205, 205, 205, 205, 371, - 393, 172, 248, 249, 250, 248, 248, 248, 248, 248, - 253, 253, 254, 255, 255, 255, 255, 255, 214, 86, - 85, 372, 209, 209, 209, 209, 209, 209, 209, 209, - 86, 121, 121, 209, 209, 209, 209, 209, 222, 222, - - 222, 222, 222, 222, 222, 222, 387, 387, 387, 387, - 387, 388, 209, 209, 209, 209, 209, 211, 212, 213, - 213, 213, 213, 213, 213, 214, 172, 86, 215, 215, - 215, 215, 215, 263, 263, 263, 263, 263, 263, 263, - 263, 373, 421, 482, 482, 482, 172, 215, 215, 215, - 215, 215, 172, 218, 219, 220, 218, 218, 218, 218, - 218, 221, 443, 374, 222, 222, 222, 222, 222, 609, - 172, 262, 262, 262, 262, 262, 262, 262, 262, 261, - 393, 122, 367, 222, 222, 222, 222, 222, 223, 223, - 223, 223, 223, 223, 223, 223, 431, 259, 172, 223, - - 223, 223, 223, 223, 368, 281, 282, 283, 281, 281, - 281, 281, 281, 371, 483, 172, 609, 172, 209, 209, - 209, 209, 209, 234, 307, 235, 235, 235, 235, 235, - 235, 235, 235, 122, 290, 372, 291, 291, 291, 291, - 291, 291, 291, 291, 296, 296, 296, 296, 296, 296, - 296, 296, 214, 122, 121, 609, 239, 239, 239, 239, - 239, 239, 239, 239, 172, 393, 483, 239, 239, 239, - 239, 239, 290, 307, 292, 292, 292, 292, 292, 292, - 292, 292, 515, 515, 515, 483, 239, 239, 239, 239, - 239, 240, 240, 240, 240, 240, 240, 240, 240, 172, - - 259, 172, 240, 240, 240, 240, 240, 290, 357, 293, - 293, 293, 293, 293, 294, 291, 291, 471, 349, 471, - 349, 239, 239, 239, 239, 239, 259, 172, 260, 260, - 260, 260, 260, 260, 260, 260, 261, 86, 453, 262, - 262, 262, 262, 262, 301, 302, 303, 301, 301, 301, - 301, 301, 373, 577, 577, 152, 152, 453, 262, 262, - 262, 262, 262, 172, 266, 267, 268, 266, 266, 266, - 266, 266, 269, 453, 374, 270, 270, 270, 270, 270, - 270, 270, 270, 270, 270, 270, 270, 270, 396, 396, - 396, 396, 396, 397, 270, 270, 270, 270, 270, 259, - - 172, 305, 305, 305, 305, 305, 305, 305, 305, 261, - 537, 537, 304, 304, 304, 304, 304, 259, 172, 305, - 305, 305, 305, 305, 305, 367, 371, 261, 350, 393, - 350, 304, 304, 304, 304, 304, 259, 172, 306, 306, - 306, 306, 306, 306, 306, 306, 307, 368, 372, 308, - 308, 308, 308, 308, 309, 309, 309, 309, 309, 309, - 309, 309, 413, 413, 413, 413, 413, 414, 308, 308, - 308, 308, 308, 172, 312, 313, 314, 312, 312, 312, - 312, 312, 315, 538, 538, 316, 316, 316, 316, 316, - 609, 424, 308, 308, 308, 308, 308, 308, 308, 308, - - 259, 172, 483, 483, 316, 316, 316, 316, 316, 325, - 307, 326, 326, 326, 326, 326, 326, 326, 326, 325, - 122, 327, 327, 327, 327, 327, 327, 327, 327, 325, - 342, 328, 328, 328, 328, 328, 329, 326, 326, 336, - 337, 338, 336, 336, 336, 336, 336, 290, 391, 291, - 291, 291, 291, 291, 291, 291, 291, 290, 393, 291, - 291, 291, 291, 291, 291, 291, 291, 86, 290, 122, - 291, 291, 291, 291, 291, 291, 348, 86, 351, 351, - 351, 351, 351, 352, 349, 349, 316, 316, 316, 316, - 316, 316, 316, 316, 86, 453, 509, 547, 86, 343, - - 344, 345, 343, 343, 343, 343, 343, 346, 508, 453, - 347, 347, 347, 347, 347, 259, 172, 355, 355, 355, - 355, 355, 355, 373, 466, 307, 122, 86, 342, 347, - 347, 347, 347, 347, 259, 172, 355, 355, 355, 355, - 355, 355, 355, 355, 307, 374, 467, 354, 354, 354, - 354, 354, 359, 359, 359, 359, 359, 359, 359, 359, - 427, 427, 427, 427, 427, 428, 354, 354, 354, 354, - 354, 259, 172, 356, 356, 356, 356, 356, 356, 356, - 356, 357, 257, 430, 358, 358, 358, 358, 358, 609, - 391, 358, 358, 358, 358, 358, 358, 358, 358, 124, - - 443, 429, 124, 358, 358, 358, 358, 358, 172, 362, - 363, 364, 362, 362, 362, 362, 362, 365, 420, 419, - 366, 366, 366, 366, 366, 378, 379, 380, 378, 378, - 378, 378, 378, 348, 348, 259, 172, 348, 342, 366, - 366, 366, 366, 366, 325, 357, 326, 326, 326, 326, - 326, 326, 325, 122, 326, 326, 326, 326, 326, 326, - 326, 326, 325, 609, 326, 326, 326, 326, 326, 326, - 326, 326, 565, 443, 122, 384, 385, 385, 385, 385, - 385, 385, 385, 385, 386, 386, 386, 386, 386, 386, - 386, 386, 347, 347, 347, 347, 347, 347, 347, 347, - - 257, 454, 122, 454, 86, 391, 391, 392, 392, 392, - 392, 392, 392, 392, 392, 393, 443, 214, 394, 394, - 394, 394, 394, 395, 395, 395, 395, 395, 395, 395, - 395, 446, 446, 446, 446, 446, 447, 394, 394, 394, - 394, 394, 398, 399, 400, 398, 398, 398, 398, 398, - 401, 382, 381, 402, 402, 402, 402, 402, 609, 172, - 394, 394, 394, 394, 394, 394, 394, 394, 357, 455, - 370, 455, 402, 402, 402, 402, 402, 403, 404, 405, - 403, 403, 403, 403, 403, 348, 369, 349, 349, 349, - 349, 349, 349, 366, 366, 366, 366, 366, 366, 366, - - 366, 609, 172, 412, 412, 412, 412, 412, 412, 412, - 412, 357, 259, 172, 408, 408, 408, 408, 408, 408, - 408, 408, 357, 348, 348, 407, 407, 407, 407, 407, - 259, 172, 408, 408, 408, 408, 408, 408, 468, 466, - 357, 484, 342, 484, 407, 407, 407, 407, 407, 259, - 172, 409, 409, 409, 409, 409, 409, 409, 409, 410, - 469, 467, 411, 411, 411, 411, 411, 609, 172, 411, - 411, 411, 411, 411, 411, 411, 411, 410, 485, 257, - 485, 411, 411, 411, 411, 411, 172, 415, 416, 417, - 415, 415, 415, 415, 415, 553, 214, 553, 418, 418, - - 418, 418, 418, 426, 426, 426, 426, 426, 426, 426, - 426, 464, 464, 464, 464, 464, 465, 418, 418, 418, - 418, 418, 424, 425, 425, 425, 425, 425, 425, 425, - 425, 432, 433, 434, 435, 432, 432, 432, 432, 437, - 438, 439, 437, 437, 437, 437, 437, 259, 172, 214, - 554, 122, 554, 334, 333, 332, 331, 357, 468, 86, - 402, 402, 402, 402, 402, 402, 402, 402, 391, 466, - 441, 441, 441, 441, 441, 441, 441, 441, 393, 391, - 469, 441, 441, 441, 441, 441, 441, 330, 321, 393, - 391, 467, 442, 442, 442, 442, 442, 442, 442, 442, - - 443, 320, 319, 444, 444, 444, 444, 444, 445, 445, - 445, 445, 445, 445, 445, 445, 495, 495, 495, 495, - 495, 496, 444, 444, 444, 444, 444, 448, 449, 450, - 448, 448, 448, 448, 448, 451, 318, 317, 452, 452, - 452, 452, 452, 609, 299, 444, 444, 444, 444, 444, - 444, 444, 444, 259, 172, 257, 214, 452, 452, 452, - 452, 452, 453, 410, 456, 456, 456, 456, 456, 457, - 454, 454, 418, 418, 418, 418, 418, 418, 418, 418, - 609, 172, 463, 463, 463, 463, 463, 463, 463, 463, - 410, 259, 172, 460, 460, 460, 460, 460, 460, 460, - - 460, 410, 295, 214, 459, 459, 459, 459, 459, 259, - 172, 460, 460, 460, 460, 460, 460, 468, 106, 410, - 288, 287, 286, 459, 459, 459, 459, 459, 259, 172, - 461, 461, 461, 461, 461, 461, 461, 461, 285, 469, - 284, 462, 462, 462, 462, 462, 609, 391, 462, 462, - 462, 462, 462, 462, 462, 462, 100, 492, 277, 582, - 462, 462, 462, 462, 462, 472, 473, 474, 475, 472, - 472, 472, 472, 478, 478, 478, 478, 478, 478, 478, - 478, 479, 479, 479, 479, 479, 480, 481, 481, 86, - 276, 275, 592, 122, 476, 609, 477, 477, 477, 477, - - 477, 477, 477, 477, 483, 492, 486, 486, 486, 486, - 486, 487, 484, 484, 452, 452, 452, 452, 452, 452, - 452, 452, 122, 274, 86, 391, 273, 490, 490, 490, - 490, 490, 490, 490, 490, 443, 391, 100, 490, 490, - 490, 490, 490, 490, 214, 257, 443, 391, 391, 491, - 491, 491, 491, 491, 491, 491, 491, 492, 492, 214, - 493, 493, 493, 493, 493, 494, 494, 494, 494, 494, - 494, 494, 494, 531, 531, 531, 531, 531, 532, 493, - 493, 493, 493, 493, 497, 498, 499, 497, 497, 497, - 497, 497, 500, 106, 203, 501, 501, 501, 501, 501, - - 609, 172, 493, 493, 493, 493, 493, 493, 493, 493, - 410, 246, 245, 244, 501, 501, 501, 501, 501, 502, - 503, 504, 502, 502, 502, 502, 502, 453, 243, 454, - 454, 454, 454, 454, 454, 259, 172, 259, 172, 507, - 507, 507, 507, 507, 507, 410, 259, 172, 507, 507, - 507, 507, 507, 507, 507, 507, 509, 242, 510, 510, - 510, 510, 510, 510, 510, 510, 511, 511, 511, 511, - 511, 511, 511, 511, 512, 512, 512, 512, 512, 513, - 514, 514, 241, 520, 520, 520, 122, 516, 517, 518, - 516, 516, 516, 516, 516, 481, 481, 481, 481, 481, - - 481, 481, 481, 481, 481, 481, 481, 481, 481, 481, - 481, 86, 131, 189, 232, 86, 481, 481, 481, 481, - 481, 481, 519, 519, 519, 519, 519, 519, 519, 519, - 519, 519, 476, 229, 520, 520, 520, 521, 522, 523, - 521, 521, 521, 521, 521, 483, 228, 484, 484, 484, - 484, 484, 484, 501, 501, 501, 501, 501, 501, 501, - 501, 227, 86, 391, 226, 526, 526, 526, 526, 526, - 526, 526, 526, 492, 391, 225, 526, 526, 526, 526, - 526, 526, 224, 106, 492, 391, 391, 527, 527, 527, - 527, 527, 527, 527, 527, 528, 528, 98, 529, 529, - - 529, 529, 529, 530, 530, 530, 530, 530, 530, 530, - 530, 563, 563, 563, 563, 563, 564, 529, 529, 529, - 529, 529, 533, 534, 535, 533, 533, 533, 533, 533, - 203, 159, 160, 536, 536, 536, 536, 536, 609, 609, - 529, 529, 529, 529, 529, 529, 529, 529, 154, 528, - 154, 147, 536, 536, 536, 536, 536, 172, 539, 539, - 539, 539, 539, 540, 537, 537, 121, 145, 542, 543, - 544, 542, 542, 542, 542, 542, 514, 514, 514, 514, - 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, - 514, 514, 514, 514, 514, 514, 514, 514, 545, 545, - - 545, 545, 545, 545, 545, 545, 545, 545, 509, 201, - 546, 546, 546, 547, 391, 548, 548, 548, 548, 548, - 548, 548, 548, 547, 528, 549, 549, 549, 549, 549, - 549, 549, 549, 200, 196, 121, 128, 547, 122, 550, - 550, 550, 550, 550, 551, 548, 548, 85, 126, 519, - 519, 519, 519, 519, 519, 519, 519, 552, 189, 555, - 555, 555, 555, 555, 556, 553, 553, 536, 536, 536, - 536, 536, 536, 536, 536, 391, 122, 559, 559, 559, - 559, 559, 559, 559, 559, 528, 391, 181, 559, 559, - 559, 559, 559, 559, 180, 176, 528, 391, 106, 560, - - 560, 560, 560, 560, 560, 560, 560, 546, 546, 546, - 561, 561, 561, 561, 561, 562, 562, 562, 562, 562, - 562, 562, 562, 587, 587, 587, 587, 587, 587, 561, - 561, 561, 561, 561, 609, 122, 561, 561, 561, 561, - 561, 561, 561, 561, 172, 537, 537, 537, 537, 537, - 537, 565, 85, 566, 566, 566, 566, 566, 566, 566, - 566, 565, 106, 567, 567, 567, 567, 567, 567, 567, - 567, 565, 165, 568, 568, 568, 568, 568, 569, 566, - 566, 121, 94, 545, 545, 545, 545, 545, 545, 545, - 545, 570, 571, 572, 570, 570, 570, 570, 570, 547, - - 92, 548, 548, 548, 548, 548, 548, 548, 548, 547, - 90, 548, 548, 548, 548, 548, 548, 548, 548, 86, - 547, 88, 548, 548, 548, 548, 548, 548, 573, 574, - 575, 573, 573, 573, 573, 573, 552, 87, 553, 553, - 553, 553, 553, 553, 86, 160, 154, 147, 145, 391, - 86, 578, 578, 578, 578, 578, 578, 578, 578, 579, - 580, 581, 579, 579, 579, 579, 579, 565, 142, 566, - 566, 566, 566, 566, 566, 566, 566, 565, 141, 566, - 566, 566, 566, 566, 566, 566, 566, 122, 565, 140, - 566, 566, 566, 566, 566, 566, 582, 139, 583, 583, - - 583, 583, 583, 583, 583, 583, 582, 128, 584, 584, - 584, 584, 584, 584, 584, 584, 126, 582, 122, 585, - 585, 585, 585, 585, 586, 583, 583, 587, 587, 587, - 587, 587, 587, 587, 587, 588, 588, 588, 588, 588, - 588, 588, 588, 589, 589, 589, 589, 589, 590, 587, - 587, 592, 122, 593, 593, 593, 593, 593, 593, 593, - 593, 592, 120, 594, 594, 594, 594, 594, 594, 594, - 594, 592, 119, 595, 595, 595, 595, 595, 596, 593, - 593, 85, 118, 597, 598, 599, 597, 597, 597, 597, - 597, 582, 117, 583, 583, 583, 583, 583, 583, 583, - - 583, 582, 116, 583, 583, 583, 583, 583, 583, 583, - 583, 582, 112, 583, 583, 583, 583, 583, 583, 587, - 587, 587, 587, 587, 587, 587, 587, 587, 587, 587, - 587, 587, 587, 587, 587, 111, 110, 109, 106, 94, - 121, 86, 600, 601, 602, 600, 600, 600, 600, 600, - 592, 92, 593, 593, 593, 593, 593, 593, 593, 593, - 592, 90, 593, 593, 593, 593, 593, 593, 593, 593, - 592, 88, 593, 593, 593, 593, 593, 593, 603, 603, - 603, 603, 603, 603, 603, 603, 597, 597, 597, 597, - 597, 597, 597, 597, 87, 86, 609, 609, 609, 609, - - 122, 609, 609, 609, 609, 609, 86, 609, 609, 609, - 609, 609, 609, 609, 86, 604, 604, 604, 604, 604, - 605, 603, 603, 606, 606, 606, 606, 606, 606, 606, - 606, 600, 600, 600, 600, 600, 600, 600, 600, 609, - 609, 609, 609, 86, 609, 609, 609, 609, 609, 609, - 609, 122, 603, 603, 603, 603, 603, 603, 609, 122, - 607, 607, 607, 607, 607, 608, 606, 606, 603, 603, - 603, 603, 603, 603, 603, 603, 609, 609, 609, 609, - 86, 606, 606, 606, 606, 606, 606, 609, 122, 609, - 609, 609, 609, 609, 609, 609, 86, 606, 606, 606, - - 606, 606, 606, 606, 606, 609, 609, 609, 609, 122, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 122, 65, 65, 65, 65, - 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, - 65, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 73, 73, 73, 73, - 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, - 73, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 85, 609, 609, 609, - 85, 609, 85, 85, 85, 85, 609, 85, 85, 85, - - 85, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 91, 609, 609, 609, - 91, 609, 91, 91, 91, 91, 609, 91, 91, 91, - 91, 93, 609, 609, 609, 93, 609, 93, 93, 93, - 93, 609, 93, 93, 93, 93, 95, 609, 609, 95, - 95, 609, 95, 95, 95, 95, 609, 95, 95, 95, - 95, 105, 105, 105, 609, 609, 105, 121, 609, 609, - 609, 121, 609, 121, 121, 121, 121, 609, 121, 121, - 121, 121, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 125, 609, 609, - - 609, 125, 609, 125, 125, 125, 125, 609, 125, 125, - 125, 125, 127, 609, 609, 609, 127, 609, 127, 127, - 127, 127, 609, 127, 127, 127, 127, 129, 609, 609, - 129, 129, 609, 129, 129, 129, 129, 609, 129, 129, - 129, 129, 146, 609, 609, 146, 146, 146, 146, 146, - 146, 146, 609, 146, 609, 146, 146, 153, 609, 609, - 153, 153, 609, 153, 153, 153, 153, 153, 153, 153, - 153, 153, 157, 157, 157, 157, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 157, 157, 159, 159, 609, - 159, 609, 159, 159, 159, 159, 159, 159, 159, 159, - - 159, 159, 96, 609, 609, 96, 96, 609, 96, 96, - 96, 96, 609, 96, 96, 96, 96, 171, 171, 171, - 609, 609, 171, 173, 173, 173, 173, 609, 609, 173, - 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, - 188, 188, 188, 188, 188, 210, 210, 210, 609, 609, - 210, 216, 216, 216, 216, 609, 609, 216, 251, 251, - 251, 609, 609, 251, 252, 252, 252, 609, 609, 252, - 256, 256, 256, 609, 609, 256, 258, 258, 258, 258, - 609, 609, 258, 295, 295, 295, 609, 609, 295, 297, - 297, 297, 609, 609, 297, 298, 298, 298, 609, 609, - - 298, 300, 300, 300, 300, 609, 609, 300, 304, 304, - 304, 304, 304, 609, 609, 304, 339, 339, 339, 609, - 609, 339, 340, 340, 340, 609, 609, 340, 341, 341, - 341, 609, 609, 341, 353, 353, 353, 353, 609, 609, - 353, 354, 354, 354, 354, 354, 609, 609, 354, 389, - 389, 389, 609, 609, 389, 390, 390, 390, 609, 609, - 390, 406, 406, 406, 406, 609, 609, 406, 407, 407, - 407, 407, 407, 609, 609, 407, 436, 436, 436, 609, - 609, 436, 440, 609, 440, 440, 440, 609, 609, 440, - 458, 458, 458, 458, 609, 609, 458, 459, 459, 459, - - 459, 459, 609, 609, 459, 488, 488, 488, 609, 609, - 488, 489, 609, 489, 489, 489, 609, 609, 489, 505, - 505, 505, 505, 609, 609, 505, 506, 506, 506, 609, - 506, 609, 609, 506, 524, 524, 524, 609, 609, 524, - 525, 609, 525, 525, 525, 609, 609, 525, 541, 541, - 609, 541, 609, 609, 541, 557, 557, 557, 609, 609, - 557, 558, 609, 558, 558, 558, 609, 609, 558, 576, - 576, 576, 609, 609, 576, 577, 609, 577, 609, 577, - 609, 609, 577, 591, 609, 591, 609, 609, 591, 15, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609 - } ; - -static yyconst short int yy_chk[3851] = - { 0, - 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, 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, 2, 322, 5, 2, 71, 71, 5, 2, 5, - 322, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 6, 7, 7, 7, 6, 7, 6, 75, - 8, 8, 8, 7, 8, 40, 13, 13, 13, 13, - 8, 14, 14, 14, 14, 7, 7, 63, 75, 79, - 79, 40, 8, 8, 26, 106, 606, 115, 26, 26, - 77, 115, 81, 63, 106, 7, 29, 29, 29, 29, - 29, 29, 8, 9, 9, 9, 26, 9, 13, 77, - 186, 116, 186, 14, 28, 28, 28, 28, 28, 28, - - 28, 28, 116, 39, 26, 39, 39, 39, 39, 39, - 39, 39, 39, 47, 81, 173, 47, 47, 47, 47, - 47, 47, 47, 47, 173, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 10, 10, 10, 117, 10, 53, 53, 53, - 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, - 54, 62, 118, 62, 62, 62, 62, 62, 62, 62, - 62, 84, 84, 144, 84, 110, 118, 144, 82, 183, - 110, 117, 110, 183, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - - 10, 11, 11, 11, 11, 11, 148, 148, 182, 51, - 11, 11, 11, 51, 51, 70, 70, 70, 82, 70, - 182, 120, 140, 70, 11, 70, 120, 140, 95, 140, - 119, 51, 95, 95, 151, 151, 603, 70, 70, 113, - 113, 119, 162, 11, 12, 12, 12, 12, 12, 51, - 95, 163, 163, 12, 12, 12, 86, 70, 86, 578, - 86, 335, 86, 86, 208, 208, 86, 12, 95, 335, - 98, 98, 98, 98, 98, 98, 98, 98, 86, 86, - 86, 113, 162, 143, 143, 161, 12, 27, 205, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 98, 185, - - 27, 27, 27, 27, 27, 102, 102, 102, 102, 102, - 102, 102, 102, 187, 185, 209, 576, 27, 205, 27, - 27, 27, 27, 27, 32, 143, 187, 161, 32, 561, - 32, 231, 231, 32, 32, 209, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 238, 238, - 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, 158, 158, 34, 34, 34, 34, 34, - - 103, 103, 103, 103, 103, 103, 103, 103, 104, 104, - 104, 104, 104, 104, 34, 34, 34, 34, 34, 38, - 38, 38, 202, 38, 278, 38, 38, 216, 278, 38, - 213, 213, 213, 129, 202, 158, 216, 129, 129, 279, - 224, 38, 38, 38, 52, 235, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 129, 279, 52, 52, 52, - 52, 52, 224, 560, 131, 131, 131, 131, 131, 131, - 131, 131, 233, 129, 52, 235, 52, 52, 52, 52, - 52, 55, 558, 230, 241, 55, 233, 55, 230, 557, - 55, 55, 131, 55, 55, 55, 55, 55, 55, 55, - - 55, 55, 55, 55, 55, 555, 241, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 55, 57, 57, 57, 57, 57, 57, 57, 57, 57, - 385, 554, 57, 57, 57, 57, 57, 134, 134, 134, - 134, 134, 134, 134, 134, 136, 136, 136, 136, 136, - 136, 57, 57, 57, 57, 57, 61, 61, 61, 385, - 61, 258, 61, 61, 239, 92, 61, 92, 247, 92, - 258, 92, 92, 247, 280, 92, 260, 260, 61, 61, - - 61, 154, 553, 280, 239, 154, 260, 92, 92, 92, - 94, 154, 94, 324, 94, 541, 94, 94, 289, 97, - 94, 97, 289, 97, 154, 97, 97, 539, 324, 97, - 271, 317, 94, 94, 94, 168, 168, 168, 168, 168, - 168, 97, 97, 97, 99, 99, 99, 99, 99, 99, - 99, 99, 271, 317, 538, 99, 99, 99, 99, 99, - 135, 135, 135, 135, 135, 135, 135, 135, 192, 192, - 192, 192, 192, 192, 99, 99, 99, 99, 99, 107, - 107, 107, 107, 107, 107, 107, 107, 232, 262, 262, - 107, 107, 107, 107, 107, 122, 537, 122, 262, 122, - - 376, 122, 122, 525, 291, 122, 300, 232, 376, 107, - 107, 107, 107, 107, 377, 300, 304, 122, 122, 122, - 126, 524, 126, 232, 126, 304, 126, 126, 377, 128, - 126, 128, 326, 128, 291, 128, 128, 305, 305, 128, - 306, 306, 126, 126, 126, 165, 522, 305, 323, 165, - 306, 128, 128, 128, 130, 165, 130, 323, 130, 477, - 130, 130, 326, 521, 130, 308, 308, 165, 165, 220, - 220, 220, 220, 220, 220, 308, 130, 130, 130, 132, - 132, 132, 132, 132, 132, 132, 132, 388, 388, 477, - 132, 132, 132, 132, 132, 167, 167, 167, 167, 167, - - 167, 167, 167, 268, 268, 268, 268, 268, 268, 132, - 132, 132, 132, 132, 137, 137, 137, 137, 137, 137, - 137, 137, 422, 508, 422, 137, 137, 137, 137, 137, - 191, 191, 191, 191, 191, 191, 191, 191, 314, 314, - 314, 314, 314, 314, 137, 137, 137, 137, 137, 166, - 392, 166, 166, 166, 166, 166, 166, 166, 166, 320, - 392, 506, 204, 204, 204, 204, 204, 204, 204, 204, - 212, 212, 212, 212, 212, 212, 212, 212, 212, 166, - 169, 320, 169, 169, 169, 169, 169, 169, 169, 169, - 204, 428, 428, 169, 169, 169, 169, 169, 217, 217, - - 217, 217, 217, 217, 217, 217, 338, 338, 338, 338, - 338, 338, 169, 169, 169, 169, 169, 172, 172, 172, - 172, 172, 172, 172, 172, 172, 503, 375, 172, 172, - 172, 172, 172, 219, 219, 219, 219, 219, 219, 219, - 219, 321, 375, 435, 435, 435, 502, 172, 172, 172, - 172, 172, 174, 174, 174, 174, 174, 174, 174, 174, - 174, 174, 489, 321, 174, 174, 174, 174, 174, 222, - 353, 222, 222, 222, 222, 222, 222, 222, 222, 353, - 488, 383, 330, 174, 174, 174, 174, 174, 175, 175, - 175, 175, 175, 175, 175, 175, 383, 461, 461, 175, - - 175, 175, 175, 175, 330, 234, 234, 234, 234, 234, - 234, 234, 234, 333, 486, 354, 462, 462, 175, 175, - 175, 175, 175, 190, 354, 190, 190, 190, 190, 190, - 190, 190, 190, 234, 248, 333, 248, 248, 248, 248, - 248, 248, 248, 248, 253, 253, 253, 253, 253, 253, - 253, 253, 253, 190, 193, 394, 193, 193, 193, 193, - 193, 193, 193, 193, 406, 394, 485, 193, 193, 193, - 193, 193, 249, 406, 249, 249, 249, 249, 249, 249, - 249, 249, 475, 475, 475, 484, 193, 193, 193, 193, - 193, 195, 195, 195, 195, 195, 195, 195, 195, 407, - - 507, 507, 195, 195, 195, 195, 195, 250, 407, 250, - 250, 250, 250, 250, 250, 250, 250, 423, 649, 423, - 649, 195, 195, 195, 195, 195, 218, 218, 218, 218, - 218, 218, 218, 218, 218, 218, 218, 423, 456, 218, - 218, 218, 218, 218, 259, 259, 259, 259, 259, 259, - 259, 259, 334, 564, 564, 626, 626, 455, 218, 218, - 218, 218, 218, 221, 221, 221, 221, 221, 221, 221, - 221, 221, 221, 454, 334, 221, 221, 221, 221, 221, - 261, 261, 261, 261, 261, 261, 261, 261, 345, 345, - 345, 345, 345, 345, 221, 221, 221, 221, 221, 263, - - 263, 263, 263, 263, 263, 263, 263, 263, 263, 263, - 671, 671, 263, 263, 263, 263, 263, 265, 265, 265, - 265, 265, 265, 265, 265, 367, 371, 265, 650, 440, - 650, 263, 263, 263, 263, 263, 266, 266, 266, 266, - 266, 266, 266, 266, 266, 266, 266, 367, 371, 266, - 266, 266, 266, 266, 267, 267, 267, 267, 267, 267, - 267, 267, 364, 364, 364, 364, 364, 364, 266, 266, - 266, 266, 266, 269, 269, 269, 269, 269, 269, 269, - 269, 269, 269, 672, 672, 269, 269, 269, 269, 269, - 270, 425, 270, 270, 270, 270, 270, 270, 270, 270, - - 355, 355, 438, 437, 269, 269, 269, 269, 269, 281, - 355, 281, 281, 281, 281, 281, 281, 281, 281, 282, - 425, 282, 282, 282, 282, 282, 282, 282, 282, 283, - 436, 283, 283, 283, 283, 283, 283, 283, 283, 290, - 290, 290, 290, 290, 290, 290, 290, 292, 441, 292, - 292, 292, 292, 292, 292, 292, 292, 293, 441, 293, - 293, 293, 293, 293, 293, 293, 293, 290, 294, 431, - 294, 294, 294, 294, 294, 294, 303, 421, 303, 303, - 303, 303, 303, 303, 303, 303, 307, 307, 307, 307, - 307, 307, 307, 307, 470, 404, 510, 548, 294, 299, - - 299, 299, 299, 299, 299, 299, 299, 299, 470, 403, - 299, 299, 299, 299, 299, 311, 311, 311, 311, 311, - 311, 311, 311, 373, 419, 311, 510, 548, 390, 299, - 299, 299, 299, 299, 309, 309, 309, 309, 309, 309, - 309, 309, 309, 309, 309, 373, 419, 309, 309, 309, - 309, 309, 313, 313, 313, 313, 313, 313, 313, 313, - 380, 380, 380, 380, 380, 380, 309, 309, 309, 309, - 309, 312, 312, 312, 312, 312, 312, 312, 312, 312, - 312, 312, 389, 382, 312, 312, 312, 312, 312, 316, - 442, 316, 316, 316, 316, 316, 316, 316, 316, 634, - - 442, 381, 634, 312, 312, 312, 312, 312, 315, 315, - 315, 315, 315, 315, 315, 315, 315, 315, 370, 369, - 315, 315, 315, 315, 315, 325, 325, 325, 325, 325, - 325, 325, 325, 351, 350, 356, 356, 349, 341, 315, - 315, 315, 315, 315, 329, 356, 329, 329, 329, 329, - 329, 329, 327, 325, 327, 327, 327, 327, 327, 327, - 327, 327, 328, 444, 328, 328, 328, 328, 328, 328, - 328, 328, 566, 444, 329, 336, 336, 336, 336, 336, - 336, 336, 336, 336, 337, 337, 337, 337, 337, 337, - 337, 337, 342, 342, 342, 342, 342, 342, 342, 342, - - 340, 659, 566, 659, 336, 343, 490, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 490, 339, 343, 343, - 343, 343, 343, 344, 344, 344, 344, 344, 344, 344, - 344, 400, 400, 400, 400, 400, 400, 343, 343, 343, - 343, 343, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 332, 331, 346, 346, 346, 346, 346, 347, 458, - 347, 347, 347, 347, 347, 347, 347, 347, 458, 660, - 319, 660, 346, 346, 346, 346, 346, 348, 348, 348, - 348, 348, 348, 348, 348, 352, 318, 352, 352, 352, - 352, 352, 352, 357, 357, 357, 357, 357, 357, 357, - - 357, 358, 358, 363, 363, 363, 363, 363, 363, 363, - 363, 358, 359, 359, 359, 359, 359, 359, 359, 359, - 359, 359, 359, 302, 301, 359, 359, 359, 359, 359, - 361, 361, 361, 361, 361, 361, 361, 361, 420, 429, - 361, 663, 298, 663, 359, 359, 359, 359, 359, 362, - 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, - 420, 429, 362, 362, 362, 362, 362, 366, 459, 366, - 366, 366, 366, 366, 366, 366, 366, 459, 664, 297, - 664, 362, 362, 362, 362, 362, 365, 365, 365, 365, - 365, 365, 365, 365, 365, 674, 296, 674, 365, 365, - - 365, 365, 365, 379, 379, 379, 379, 379, 379, 379, - 379, 417, 417, 417, 417, 417, 417, 365, 365, 365, - 365, 365, 378, 378, 378, 378, 378, 378, 378, 378, - 378, 384, 384, 384, 384, 384, 384, 384, 384, 391, - 391, 391, 391, 391, 391, 391, 391, 408, 408, 295, - 675, 378, 675, 288, 287, 286, 285, 408, 430, 384, - 393, 393, 393, 393, 393, 393, 393, 393, 395, 466, - 395, 395, 395, 395, 395, 395, 395, 395, 395, 397, - 430, 397, 397, 397, 397, 397, 397, 284, 277, 397, - 398, 466, 398, 398, 398, 398, 398, 398, 398, 398, - - 398, 276, 275, 398, 398, 398, 398, 398, 399, 399, - 399, 399, 399, 399, 399, 399, 450, 450, 450, 450, - 450, 450, 398, 398, 398, 398, 398, 401, 401, 401, - 401, 401, 401, 401, 401, 401, 274, 273, 401, 401, - 401, 401, 401, 402, 257, 402, 402, 402, 402, 402, - 402, 402, 402, 409, 409, 256, 255, 401, 401, 401, - 401, 401, 405, 409, 405, 405, 405, 405, 405, 405, - 405, 405, 410, 410, 410, 410, 410, 410, 410, 410, - 411, 411, 416, 416, 416, 416, 416, 416, 416, 416, - 411, 412, 412, 412, 412, 412, 412, 412, 412, 412, - - 412, 412, 254, 252, 412, 412, 412, 412, 412, 414, - 414, 414, 414, 414, 414, 414, 414, 468, 251, 414, - 246, 245, 244, 412, 412, 412, 412, 412, 415, 415, - 415, 415, 415, 415, 415, 415, 415, 415, 243, 468, - 242, 415, 415, 415, 415, 415, 418, 491, 418, 418, - 418, 418, 418, 418, 418, 418, 240, 491, 229, 583, - 415, 415, 415, 415, 415, 424, 424, 424, 424, 424, - 424, 424, 424, 433, 433, 433, 433, 433, 433, 433, - 433, 434, 434, 434, 434, 434, 434, 434, 434, 583, - 228, 227, 593, 424, 432, 493, 432, 432, 432, 432, - - 432, 432, 432, 432, 439, 493, 439, 439, 439, 439, - 439, 439, 439, 439, 443, 443, 443, 443, 443, 443, - 443, 443, 593, 226, 432, 445, 225, 445, 445, 445, - 445, 445, 445, 445, 445, 445, 447, 223, 447, 447, - 447, 447, 447, 447, 215, 214, 447, 448, 526, 448, - 448, 448, 448, 448, 448, 448, 448, 448, 526, 211, - 448, 448, 448, 448, 448, 449, 449, 449, 449, 449, - 449, 449, 449, 499, 499, 499, 499, 499, 499, 448, - 448, 448, 448, 448, 451, 451, 451, 451, 451, 451, - 451, 451, 451, 210, 203, 451, 451, 451, 451, 451, - - 452, 505, 452, 452, 452, 452, 452, 452, 452, 452, - 505, 201, 200, 199, 451, 451, 451, 451, 451, 453, - 453, 453, 453, 453, 453, 453, 453, 457, 198, 457, - 457, 457, 457, 457, 457, 460, 460, 465, 465, 465, - 465, 465, 465, 465, 465, 460, 463, 463, 463, 463, - 463, 463, 463, 463, 463, 463, 472, 197, 472, 472, - 472, 472, 472, 472, 472, 472, 473, 473, 473, 473, - 473, 473, 473, 473, 474, 474, 474, 474, 474, 474, - 474, 474, 196, 520, 520, 520, 472, 476, 476, 476, - 476, 476, 476, 476, 476, 478, 478, 478, 478, 478, - - 478, 478, 478, 479, 479, 479, 479, 479, 479, 479, - 479, 520, 194, 188, 184, 476, 480, 480, 480, 480, - 480, 480, 480, 480, 481, 481, 481, 481, 481, 481, - 481, 481, 482, 181, 482, 482, 482, 483, 483, 483, - 483, 483, 483, 483, 483, 487, 180, 487, 487, 487, - 487, 487, 487, 492, 492, 492, 492, 492, 492, 492, - 492, 179, 482, 494, 178, 494, 494, 494, 494, 494, - 494, 494, 494, 494, 496, 177, 496, 496, 496, 496, - 496, 496, 176, 171, 496, 497, 527, 497, 497, 497, - 497, 497, 497, 497, 497, 497, 527, 170, 497, 497, - - 497, 497, 497, 498, 498, 498, 498, 498, 498, 498, - 498, 535, 535, 535, 535, 535, 535, 497, 497, 497, - 497, 497, 500, 500, 500, 500, 500, 500, 500, 500, - 164, 160, 159, 500, 500, 500, 500, 500, 501, 529, - 501, 501, 501, 501, 501, 501, 501, 501, 157, 529, - 153, 147, 500, 500, 500, 500, 500, 504, 504, 504, - 504, 504, 504, 504, 504, 504, 509, 145, 509, 509, - 509, 509, 509, 509, 509, 509, 511, 511, 511, 511, - 511, 511, 511, 511, 512, 512, 512, 512, 512, 512, - 512, 512, 513, 513, 513, 513, 513, 513, 513, 513, - - 514, 514, 514, 514, 514, 514, 514, 514, 515, 142, - 515, 515, 515, 516, 559, 516, 516, 516, 516, 516, - 516, 516, 516, 517, 559, 517, 517, 517, 517, 517, - 517, 517, 517, 141, 139, 133, 127, 518, 515, 518, - 518, 518, 518, 518, 518, 518, 518, 519, 125, 519, - 519, 519, 519, 519, 519, 519, 519, 523, 123, 523, - 523, 523, 523, 523, 523, 523, 523, 528, 528, 528, - 528, 528, 528, 528, 528, 530, 121, 530, 530, 530, - 530, 530, 530, 530, 530, 530, 532, 112, 532, 532, - 532, 532, 532, 532, 111, 109, 532, 533, 105, 533, - - 533, 533, 533, 533, 533, 533, 533, 546, 546, 546, - 533, 533, 533, 533, 533, 534, 534, 534, 534, 534, - 534, 534, 534, 590, 590, 590, 590, 590, 590, 533, - 533, 533, 533, 533, 536, 546, 536, 536, 536, 536, - 536, 536, 536, 536, 540, 540, 540, 540, 540, 540, - 540, 542, 101, 542, 542, 542, 542, 542, 542, 542, - 542, 543, 100, 543, 543, 543, 543, 543, 543, 543, - 543, 544, 96, 544, 544, 544, 544, 544, 544, 544, - 544, 545, 93, 545, 545, 545, 545, 545, 545, 545, - 545, 547, 547, 547, 547, 547, 547, 547, 547, 549, - - 91, 549, 549, 549, 549, 549, 549, 549, 549, 550, - 89, 550, 550, 550, 550, 550, 550, 550, 550, 547, - 551, 88, 551, 551, 551, 551, 551, 551, 552, 552, - 552, 552, 552, 552, 552, 552, 556, 87, 556, 556, - 556, 556, 556, 556, 85, 80, 73, 67, 64, 562, - 551, 562, 562, 562, 562, 562, 562, 562, 562, 565, - 565, 565, 565, 565, 565, 565, 565, 567, 60, 567, - 567, 567, 567, 567, 567, 567, 567, 568, 59, 568, - 568, 568, 568, 568, 568, 568, 568, 565, 569, 58, - 569, 569, 569, 569, 569, 569, 570, 56, 570, 570, - - 570, 570, 570, 570, 570, 570, 571, 50, 571, 571, - 571, 571, 571, 571, 571, 571, 48, 572, 569, 572, - 572, 572, 572, 572, 572, 572, 572, 573, 573, 573, - 573, 573, 573, 573, 573, 574, 574, 574, 574, 574, - 574, 574, 574, 575, 575, 575, 575, 575, 575, 575, - 575, 579, 46, 579, 579, 579, 579, 579, 579, 579, - 579, 580, 45, 580, 580, 580, 580, 580, 580, 580, - 580, 581, 44, 581, 581, 581, 581, 581, 581, 581, - 581, 582, 43, 582, 582, 582, 582, 582, 582, 582, - 582, 584, 42, 584, 584, 584, 584, 584, 584, 584, - - 584, 585, 41, 585, 585, 585, 585, 585, 585, 585, - 585, 586, 37, 586, 586, 586, 586, 586, 586, 588, - 588, 588, 588, 588, 588, 588, 588, 589, 589, 589, - 589, 589, 589, 589, 589, 36, 35, 33, 30, 24, - 592, 586, 592, 592, 592, 592, 592, 592, 592, 592, - 594, 21, 594, 594, 594, 594, 594, 594, 594, 594, - 595, 20, 595, 595, 595, 595, 595, 595, 595, 595, - 596, 19, 596, 596, 596, 596, 596, 596, 597, 597, - 597, 597, 597, 597, 597, 597, 598, 598, 598, 598, - 598, 598, 598, 598, 17, 16, 15, 0, 0, 0, - - 596, 0, 0, 0, 0, 0, 597, 0, 0, 0, - 0, 0, 0, 0, 598, 599, 599, 599, 599, 599, - 599, 599, 599, 600, 600, 600, 600, 600, 600, 600, - 600, 601, 601, 601, 601, 601, 601, 601, 601, 0, - 0, 0, 0, 599, 0, 0, 0, 0, 0, 0, - 0, 600, 605, 605, 605, 605, 605, 605, 0, 601, - 602, 602, 602, 602, 602, 602, 602, 602, 604, 604, - 604, 604, 604, 604, 604, 604, 0, 0, 0, 0, - 605, 608, 608, 608, 608, 608, 608, 0, 602, 0, - 0, 0, 0, 0, 0, 0, 604, 607, 607, 607, - - 607, 607, 607, 607, 607, 0, 0, 0, 0, 608, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 607, 610, 610, 610, 610, - 610, 610, 610, 610, 610, 610, 610, 610, 610, 610, - 610, 611, 611, 611, 611, 611, 611, 611, 611, 611, - 611, 611, 611, 611, 611, 611, 612, 612, 612, 612, - 612, 612, 612, 612, 612, 612, 612, 612, 612, 612, - 612, 613, 613, 613, 613, 613, 613, 613, 613, 613, - 613, 613, 613, 613, 613, 613, 614, 0, 0, 0, - 614, 0, 614, 614, 614, 614, 0, 614, 614, 614, - - 614, 615, 615, 615, 615, 615, 615, 615, 615, 615, - 615, 615, 615, 615, 615, 615, 616, 0, 0, 0, - 616, 0, 616, 616, 616, 616, 0, 616, 616, 616, - 616, 617, 0, 0, 0, 617, 0, 617, 617, 617, - 617, 0, 617, 617, 617, 617, 618, 0, 0, 618, - 618, 0, 618, 618, 618, 618, 0, 618, 618, 618, - 618, 619, 619, 619, 0, 0, 619, 620, 0, 0, - 0, 620, 0, 620, 620, 620, 620, 0, 620, 620, - 620, 620, 621, 621, 621, 621, 621, 621, 621, 621, - 621, 621, 621, 621, 621, 621, 621, 622, 0, 0, - - 0, 622, 0, 622, 622, 622, 622, 0, 622, 622, - 622, 622, 623, 0, 0, 0, 623, 0, 623, 623, - 623, 623, 0, 623, 623, 623, 623, 624, 0, 0, - 624, 624, 0, 624, 624, 624, 624, 0, 624, 624, - 624, 624, 625, 0, 0, 625, 625, 625, 625, 625, - 625, 625, 0, 625, 0, 625, 625, 627, 0, 0, - 627, 627, 0, 627, 627, 627, 627, 627, 627, 627, - 627, 627, 628, 628, 628, 628, 628, 628, 628, 628, - 628, 628, 628, 628, 628, 628, 628, 629, 629, 0, - 629, 0, 629, 629, 629, 629, 629, 629, 629, 629, - - 629, 629, 630, 0, 0, 630, 630, 0, 630, 630, - 630, 630, 0, 630, 630, 630, 630, 631, 631, 631, - 0, 0, 631, 632, 632, 632, 632, 0, 0, 632, - 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, - 633, 633, 633, 633, 633, 635, 635, 635, 0, 0, - 635, 636, 636, 636, 636, 0, 0, 636, 637, 637, - 637, 0, 0, 637, 638, 638, 638, 0, 0, 638, - 639, 639, 639, 0, 0, 639, 640, 640, 640, 640, - 0, 0, 640, 641, 641, 641, 0, 0, 641, 642, - 642, 642, 0, 0, 642, 643, 643, 643, 0, 0, - - 643, 644, 644, 644, 644, 0, 0, 644, 645, 645, - 645, 645, 645, 0, 0, 645, 646, 646, 646, 0, - 0, 646, 647, 647, 647, 0, 0, 647, 648, 648, - 648, 0, 0, 648, 651, 651, 651, 651, 0, 0, - 651, 652, 652, 652, 652, 652, 0, 0, 652, 653, - 653, 653, 0, 0, 653, 654, 654, 654, 0, 0, - 654, 655, 655, 655, 655, 0, 0, 655, 656, 656, - 656, 656, 656, 0, 0, 656, 657, 657, 657, 0, - 0, 657, 658, 0, 658, 658, 658, 0, 0, 658, - 661, 661, 661, 661, 0, 0, 661, 662, 662, 662, - - 662, 662, 0, 0, 662, 665, 665, 665, 0, 0, - 665, 666, 0, 666, 666, 666, 0, 0, 666, 667, - 667, 667, 667, 0, 0, 667, 668, 668, 668, 0, - 668, 0, 0, 668, 669, 669, 669, 0, 0, 669, - 670, 0, 670, 670, 670, 0, 0, 670, 673, 673, - 0, 673, 0, 0, 673, 676, 676, 676, 0, 0, - 676, 677, 0, 677, 677, 677, 0, 0, 677, 678, - 678, 678, 0, 0, 678, 679, 0, 679, 0, 679, - 0, 0, 679, 680, 0, 680, 0, 0, 680, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609 - } ; - -static yy_state_type yy_last_accepting_state; -static char *yy_last_accepting_cpos; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -char *yytext; -#line 1 "parse.lex" -#define INITIAL 0 -#line 2 "parse.lex" -/* - * Copyright (c) 1996, 1998-2004, 2007 - * 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. - * 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. - * - * 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. - */ - -#include - -#include -#include -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif /* STDC_HEADERS */ -#ifdef HAVE_STRING_H -# include -#else -# ifdef HAVE_STRINGS_H -# include -# endif -#endif /* HAVE_STRING_H */ -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ -#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) -# include -#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ -#include -#include "sudo.h" -#include "parse.h" -#include - -#ifndef lint -__unused static const char rcsid[] = "$Sudo: lex.yy.c,v 1.46.2.11 2008/06/26 11:53:49 millert Exp $"; -#endif /* lint */ - -#undef yywrap /* guard against a yywrap macro */ - -extern YYSTYPE yylval; -extern int clearaliases; -int sudolineno = 1; -static int sawspace = 0; -static int arg_len = 0; -static int arg_size = 0; - -static int ipv6_valid __P((const char *s)); -static void _fill __P((char *, int, int)); -static void append __P((char *, int)); -static void fill_cmnd __P((char *, int)); -static void fill_args __P((char *, int, int)); -extern void reset_aliases __P((void)); -extern void yyerror __P((char *)); - -#define fill(a, b) _fill(a, b, 0) - -/* realloc() to size + COMMANDARGINC to make room for command args */ -#define COMMANDARGINC 64 - -#ifdef TRACELEXER -#define LEXTRACE(msg) fputs(msg, stderr) -#else -#define LEXTRACE(msg) -#endif -/* XXX - convert GOTRUNAS to exclusive state (GOTDEFS cannot be) */ -#define GOTRUNAS 1 - -#define GOTDEFS 2 - -#define GOTCMND 3 - -#define STARTDEFS 4 - -#define INDEFS 5 - -#define INSTR 6 - -#line 1527 "lex.yy.c" - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int yywrap YY_PROTO(( void )); -#else -extern int yywrap YY_PROTO(( void )); -#endif -#endif - -#ifndef YY_NO_UNPUT -static void yyunput YY_PROTO(( int c, char *buf_ptr )); -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen YY_PROTO(( yyconst char * )); -#endif - -#ifndef YY_NO_INPUT -#ifdef __cplusplus -static int yyinput YY_PROTO(( void )); -#else -static int input YY_PROTO(( void )); -#endif -#endif - -#if defined(YY_STACK_USED) && YY_STACK_USED -static int yy_start_stack_ptr = 0; -static int yy_start_stack_depth = 0; -static int *yy_start_stack = 0; -#ifndef YY_NO_PUSH_STATE -static void yy_push_state YY_PROTO(( int new_state )); -#endif -#ifndef YY_NO_POP_STATE -static void yy_pop_state YY_PROTO(( void )); -#endif -#ifndef YY_NO_TOP_STATE -static int yy_top_state YY_PROTO(( void )); -#endif - -#else -#define YY_NO_PUSH_STATE 1 -#define YY_NO_POP_STATE 1 -#define YY_NO_TOP_STATE 1 -#endif - -#ifdef YY_MALLOC_DECL -YY_MALLOC_DECL -#else -#ifdef __STDC__ -#ifndef __cplusplus -#include -#endif -#else -/* Just try to get by without declaring the routines. This will fail - * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) - * or sizeof(void*) != sizeof(int). - */ -#endif -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#define YY_READ_BUF_SIZE 8192 -#endif - -/* Copy whatever the last rule matched to the standard output. */ - -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( yy_current_buffer->yy_is_interactive ) \ - { \ - int c = '*', n; \ - for ( n = 0; n < max_size && \ - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ - && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL int yylex YY_PROTO(( void )) -#endif - -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK break; -#endif - -#define YY_RULE_SETUP \ - if ( yyleng > 0 ) \ - yy_current_buffer->yy_at_bol = \ - (yytext[yyleng - 1] == '\n'); \ - YY_USER_ACTION - -YY_DECL - { - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; - -#line 108 "parse.lex" - -#line 1683 "lex.yy.c" - - if ( yy_init ) - { - yy_init = 0; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! yy_start ) - yy_start = 1; /* first start state */ - - if ( ! yyin ) - yyin = stdin; - - if ( ! yyout ) - yyout = stdout; - - if ( ! yy_current_buffer ) - yy_current_buffer = - yy_create_buffer( yyin, YY_BUF_SIZE ); - - yy_load_buffer_state(); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = yy_c_buf_p; - - /* Support of yytext. */ - *yy_cp = yy_hold_char; - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = yy_start; - yy_current_state += YY_AT_BOL(); -yy_match: - do - { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - 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 >= 610 ) - 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] != 3790 ); - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; - yy_act = yy_accept[yy_current_state]; - } - - YY_DO_BEFORE_ACTION; - - -do_action: /* This label is used only to access EOF actions. */ - - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = yy_hold_char; - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 109 "parse.lex" -BEGIN STARTDEFS; - YY_BREAK -case 2: -YY_RULE_SETUP -#line 111 "parse.lex" -{ - BEGIN INDEFS; - LEXTRACE("DEFVAR "); - fill(yytext, yyleng); - return(DEFVAR); - } - YY_BREAK - -case 3: -YY_RULE_SETUP -#line 119 "parse.lex" -{ - BEGIN STARTDEFS; - LEXTRACE(", "); - return(','); - } /* return ',' */ - YY_BREAK -case 4: -YY_RULE_SETUP -#line 125 "parse.lex" -{ - LEXTRACE("= "); - return('='); - } /* return '=' */ - YY_BREAK -case 5: -YY_RULE_SETUP -#line 130 "parse.lex" -{ - LEXTRACE("+= "); - return('+'); - } /* return '+' */ - YY_BREAK -case 6: -YY_RULE_SETUP -#line 135 "parse.lex" -{ - LEXTRACE("-= "); - return('-'); - } /* return '-' */ - YY_BREAK -case 7: -YY_RULE_SETUP -#line 140 "parse.lex" -{ - LEXTRACE("BEGINSTR "); - yylval.string = NULL; - BEGIN INSTR; - } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 146 "parse.lex" -{ - LEXTRACE("WORD(2) "); - fill(yytext, yyleng); - return(WORD); - } - YY_BREAK - - -case 9: -YY_RULE_SETUP -#line 154 "parse.lex" -{ - /* Line continuation char followed by newline. */ - ++sudolineno; - LEXTRACE("\n"); - } - YY_BREAK -case 10: -YY_RULE_SETUP -#line 160 "parse.lex" -{ - LEXTRACE("ENDSTR "); - BEGIN INDEFS; - return(WORD); - } - YY_BREAK -case 11: -YY_RULE_SETUP -#line 166 "parse.lex" -{ - LEXTRACE("BACKSLASH "); - append(yytext, yyleng); - } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 171 "parse.lex" -{ - LEXTRACE("STRBODY "); - append(yytext, yyleng); - } - YY_BREAK - - -case 13: -YY_RULE_SETUP -#line 178 "parse.lex" -{ - /* quoted fnmatch glob char, pass verbatim */ - LEXTRACE("QUOTEDCHAR "); - fill_args(yytext, 2, sawspace); - sawspace = FALSE; - } - YY_BREAK -case 14: -YY_RULE_SETUP -#line 185 "parse.lex" -{ - /* quoted sudoers special char, strip backslash */ - LEXTRACE("QUOTEDCHAR "); - fill_args(yytext + 1, 1, sawspace); - sawspace = FALSE; - } - YY_BREAK -case 15: -YY_RULE_SETUP -#line 192 "parse.lex" -{ - BEGIN INITIAL; - unput(*yytext); - return(COMMAND); - } /* end of command line args */ - YY_BREAK -case 16: -YY_RULE_SETUP -#line 198 "parse.lex" -{ - LEXTRACE("ARG "); - fill_args(yytext, yyleng, sawspace); - sawspace = FALSE; - } /* a command line arg */ - YY_BREAK - -case 17: -YY_RULE_SETUP -#line 205 "parse.lex" -{ - BEGIN GOTDEFS; - switch (yytext[8]) { - case ':': - LEXTRACE("DEFAULTS_USER "); - return(DEFAULTS_USER); - case '>': - LEXTRACE("DEFAULTS_RUNAS "); - return(DEFAULTS_RUNAS); - case '@': - LEXTRACE("DEFAULTS_HOST "); - return(DEFAULTS_HOST); - default: - LEXTRACE("DEFAULTS "); - return(DEFAULTS); - } - } - YY_BREAK -case 18: -YY_RULE_SETUP -#line 223 "parse.lex" -{ - fill(yytext, yyleng); - switch (*yytext) { - case 'H': - LEXTRACE("HOSTALIAS "); - return(HOSTALIAS); - case 'C': - LEXTRACE("CMNDALIAS "); - return(CMNDALIAS); - case 'U': - LEXTRACE("USERALIAS "); - return(USERALIAS); - case 'R': - LEXTRACE("RUNASALIAS "); - BEGIN GOTRUNAS; - return(RUNASALIAS); - } - } - YY_BREAK -case 19: -YY_RULE_SETUP -#line 242 "parse.lex" -{ - /* cmnd does not require passwd for this user */ - LEXTRACE("NOPASSWD "); - return(NOPASSWD); - } - YY_BREAK -case 20: -YY_RULE_SETUP -#line 248 "parse.lex" -{ - /* cmnd requires passwd for this user */ - LEXTRACE("PASSWD "); - return(PASSWD); - } - YY_BREAK -case 21: -YY_RULE_SETUP -#line 254 "parse.lex" -{ - LEXTRACE("NOEXEC "); - return(NOEXEC); - } - YY_BREAK -case 22: -YY_RULE_SETUP -#line 259 "parse.lex" -{ - LEXTRACE("EXEC "); - return(EXEC); - } - YY_BREAK -case 23: -YY_RULE_SETUP -#line 264 "parse.lex" -{ - LEXTRACE("SETENV "); - return(SETENV); - } - YY_BREAK -case 24: -YY_RULE_SETUP -#line 269 "parse.lex" -{ - LEXTRACE("NOSETENV "); - return(NOSETENV); - } - YY_BREAK -case 25: -YY_RULE_SETUP -#line 274 "parse.lex" -{ - /* netgroup */ - fill(yytext, yyleng); - LEXTRACE("NETGROUP "); - return(NETGROUP); - } - YY_BREAK -case 26: -YY_RULE_SETUP -#line 281 "parse.lex" -{ - /* UN*X group */ - fill(yytext, yyleng); - LEXTRACE("GROUP "); - return(USERGROUP); - } - YY_BREAK -case 27: -YY_RULE_SETUP -#line 288 "parse.lex" -{ - fill(yytext, yyleng); - LEXTRACE("NTWKADDR "); - return(NTWKADDR); - } - YY_BREAK -case 28: -YY_RULE_SETUP -#line 294 "parse.lex" -{ - fill(yytext, yyleng); - LEXTRACE("NTWKADDR "); - return(NTWKADDR); - } - YY_BREAK -case 29: -YY_RULE_SETUP -#line 300 "parse.lex" -{ - if (!ipv6_valid(yytext)) { - LEXTRACE("ERROR "); - return(ERROR); - } - fill(yytext, yyleng); - LEXTRACE("NTWKADDR "); - return(NTWKADDR); - } - YY_BREAK -case 30: -YY_RULE_SETUP -#line 310 "parse.lex" -{ - if (!ipv6_valid(yytext)) { - LEXTRACE("ERROR "); - return(ERROR); - } - fill(yytext, yyleng); - LEXTRACE("NTWKADDR "); - return(NTWKADDR); - } - YY_BREAK -case 31: -YY_RULE_SETUP -#line 320 "parse.lex" -{ - BEGIN GOTRUNAS; - LEXTRACE("RUNAS "); - return (RUNAS); - } - YY_BREAK -case 32: -YY_RULE_SETUP -#line 326 "parse.lex" -{ - if (strcmp(yytext, "ALL") == 0) { - LEXTRACE("ALL "); - return(ALL); - } -#ifdef HAVE_SELINUX - /* XXX - restrict type/role to initial state */ - if (strcmp(yytext, "TYPE") == 0) { - LEXTRACE("TYPE "); - return(TYPE); - } - if (strcmp(yytext, "ROLE") == 0) { - LEXTRACE("ROLE "); - return(ROLE); - } -#endif /* HAVE_SELINUX */ - fill(yytext, yyleng); - LEXTRACE("ALIAS "); - return(ALIAS); - } - YY_BREAK -case 33: -YY_RULE_SETUP -#line 347 "parse.lex" -{ - /* username/uid that user can run command as */ - fill(yytext, yyleng); - LEXTRACE("WORD(3) "); - return(WORD); - } - YY_BREAK -case 34: -YY_RULE_SETUP -#line 354 "parse.lex" -{ - BEGIN INITIAL; - ++sudolineno; - LEXTRACE("\n"); - return(COMMENT); - } - YY_BREAK -case 35: -YY_RULE_SETUP -#line 361 "parse.lex" -{ - BEGIN INITIAL; - } - YY_BREAK -case 36: -YY_RULE_SETUP -#line 365 "parse.lex" -{ - BEGIN GOTCMND; - LEXTRACE("COMMAND "); - fill_cmnd(yytext, yyleng); - } /* sudo -e */ - YY_BREAK -case 37: -YY_RULE_SETUP -#line 371 "parse.lex" -{ - /* directories can't have args... */ - if (yytext[yyleng - 1] == '/') { - LEXTRACE("COMMAND "); - fill_cmnd(yytext, yyleng); - return(COMMAND); - } else { - BEGIN GOTCMND; - LEXTRACE("COMMAND "); - fill_cmnd(yytext, yyleng); - } - } /* a pathname */ - YY_BREAK -case 38: -YY_RULE_SETUP -#line 384 "parse.lex" -{ - /* a word */ - fill(yytext, yyleng); - LEXTRACE("WORD(4) "); - return(WORD); - } - YY_BREAK -case 39: -YY_RULE_SETUP -#line 391 "parse.lex" -{ - LEXTRACE(", "); - return(','); - } /* return ',' */ - YY_BREAK -case 40: -YY_RULE_SETUP -#line 396 "parse.lex" -{ - LEXTRACE("= "); - return('='); - } /* return '=' */ - YY_BREAK -case 41: -YY_RULE_SETUP -#line 401 "parse.lex" -{ - LEXTRACE(": "); - return(':'); - } /* return ':' */ - YY_BREAK -case 42: -YY_RULE_SETUP -#line 406 "parse.lex" -{ - if (yyleng % 2 == 1) - return('!'); /* return '!' */ - } - YY_BREAK -case 43: -YY_RULE_SETUP -#line 411 "parse.lex" -{ - BEGIN INITIAL; - ++sudolineno; - LEXTRACE("\n"); - return(COMMENT); - } /* return newline */ - YY_BREAK -case 44: -YY_RULE_SETUP -#line 418 "parse.lex" -{ /* throw away space/tabs */ - sawspace = TRUE; /* but remember for fill_args */ - } - YY_BREAK -case 45: -YY_RULE_SETUP -#line 422 "parse.lex" -{ - sawspace = TRUE; /* remember for fill_args */ - ++sudolineno; - LEXTRACE("\n\t"); - } /* throw away EOL after \ */ - YY_BREAK -case 46: -YY_RULE_SETUP -#line 428 "parse.lex" -{ - BEGIN INITIAL; - ++sudolineno; - LEXTRACE("\n"); - return(COMMENT); - } /* return comments */ - YY_BREAK -case 47: -YY_RULE_SETUP -#line 435 "parse.lex" -{ - LEXTRACE("ERROR "); - return(ERROR); - } /* parse error */ - YY_BREAK -case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(GOTRUNAS): -case YY_STATE_EOF(GOTDEFS): -case YY_STATE_EOF(GOTCMND): -case YY_STATE_EOF(STARTDEFS): -case YY_STATE_EOF(INDEFS): -case YY_STATE_EOF(INSTR): -#line 440 "parse.lex" -{ - if (YY_START != INITIAL) { - BEGIN INITIAL; - LEXTRACE("ERROR "); - return(ERROR); - } - yyterminate(); - } - YY_BREAK -case 48: -YY_RULE_SETUP -#line 449 "parse.lex" -ECHO; - YY_BREAK -#line 2261 "lex.yy.c" - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = yy_hold_char; - YY_RESTORE_YY_MORE_OFFSET - - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * yylex(). If so, then we have to assure - * consistency between yy_current_buffer and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - yy_n_chars = yy_current_buffer->yy_n_chars; - yy_current_buffer->yy_input_file = yyin; - yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state(); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = yytext_ptr + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++yy_c_buf_p; - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = yy_c_buf_p; - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer() ) - { - case EOB_ACT_END_OF_FILE: - { - yy_did_buffer_switch_on_eof = 0; - - if ( yywrap() ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = - yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state(); - - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - yy_c_buf_p = - &yy_current_buffer->yy_ch_buf[yy_n_chars]; - - yy_current_state = yy_get_previous_state(); - - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ - } /* end of yylex */ - - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ - -static int yy_get_next_buffer() - { - register char *dest = yy_current_buffer->yy_ch_buf; - register char *source = yytext_ptr; - register int number_to_move, i; - int ret_val; - - if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( yy_current_buffer->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - yy_current_buffer->yy_n_chars = yy_n_chars = 0; - - else - { - int num_to_read = - yy_current_buffer->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ -#ifdef YY_USES_REJECT - YY_FATAL_ERROR( -"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); -#else - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = yy_current_buffer; - - int yy_c_buf_p_offset = - (int) (yy_c_buf_p - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - yy_flex_realloc( (void *) b->yy_ch_buf, - b->yy_buf_size + 2 ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = yy_current_buffer->yy_buf_size - - number_to_move - 1; -#endif - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), - yy_n_chars, num_to_read ); - - yy_current_buffer->yy_n_chars = yy_n_chars; - } - - if ( yy_n_chars == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - yyrestart( yyin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - yy_current_buffer->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - yy_n_chars += number_to_move; - yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; - yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; - - yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; - - return ret_val; - } - - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - -static yy_state_type yy_get_previous_state() - { - register yy_state_type yy_current_state; - register char *yy_cp; - - yy_current_state = yy_start; - yy_current_state += YY_AT_BOL(); - - for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) - { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - 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 >= 610 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - } - - return yy_current_state; - } - - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - -#ifdef YY_USE_PROTOS -static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) -#else -static yy_state_type yy_try_NUL_trans( yy_current_state ) -yy_state_type yy_current_state; -#endif - { - register int yy_is_jam; - register char *yy_cp = yy_c_buf_p; - - register YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - 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 >= 610 ) - 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 == 609); - - return yy_is_jam ? 0 : yy_current_state; - } - - -#ifndef YY_NO_UNPUT -#ifdef YY_USE_PROTOS -static void yyunput( int c, register char *yy_bp ) -#else -static void yyunput( c, yy_bp ) -int c; -register char *yy_bp; -#endif - { - register char *yy_cp = yy_c_buf_p; - - /* undo effects of setting up yytext */ - *yy_cp = yy_hold_char; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - register int number_to_move = yy_n_chars + 2; - register char *dest = &yy_current_buffer->yy_ch_buf[ - yy_current_buffer->yy_buf_size + 2]; - register char *source = - &yy_current_buffer->yy_ch_buf[number_to_move]; - - while ( source > yy_current_buffer->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - yy_current_buffer->yy_n_chars = - yy_n_chars = yy_current_buffer->yy_buf_size; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - - yytext_ptr = yy_bp; - yy_hold_char = *yy_cp; - yy_c_buf_p = yy_cp; - } -#endif /* ifndef YY_NO_UNPUT */ - - -#ifdef __cplusplus -static int yyinput() -#else -static int input() -#endif - { - int c; - - *yy_c_buf_p = yy_hold_char; - - if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) - /* This was really a NUL. */ - *yy_c_buf_p = '\0'; - - else - { /* need more input */ - int offset = yy_c_buf_p - yytext_ptr; - ++yy_c_buf_p; - - switch ( yy_get_next_buffer() ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - yyrestart( yyin ); - - /* fall through */ - - case EOB_ACT_END_OF_FILE: - { - if ( yywrap() ) - return EOF; - - if ( ! yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = yytext_ptr + offset; - break; - } - } - } - - c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ - *yy_c_buf_p = '\0'; /* preserve yytext */ - yy_hold_char = *++yy_c_buf_p; - - yy_current_buffer->yy_at_bol = (c == '\n'); - - return c; - } - - -#ifdef YY_USE_PROTOS -void yyrestart( FILE *input_file ) -#else -void yyrestart( input_file ) -FILE *input_file; -#endif - { - if ( ! yy_current_buffer ) - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); - - yy_init_buffer( yy_current_buffer, input_file ); - yy_load_buffer_state(); - } - - -#ifdef YY_USE_PROTOS -void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) -#else -void yy_switch_to_buffer( new_buffer ) -YY_BUFFER_STATE new_buffer; -#endif - { - if ( yy_current_buffer == new_buffer ) - return; - - if ( yy_current_buffer ) - { - /* Flush out information for old buffer. */ - *yy_c_buf_p = yy_hold_char; - yy_current_buffer->yy_buf_pos = yy_c_buf_p; - yy_current_buffer->yy_n_chars = yy_n_chars; - } - - yy_current_buffer = new_buffer; - yy_load_buffer_state(); - - /* We don't actually know whether we did this switch during - * EOF (yywrap()) processing, but the only time this flag - * is looked at is after yywrap() is called, so it's safe - * to go ahead and always set it. - */ - yy_did_buffer_switch_on_eof = 1; - } - - -#ifdef YY_USE_PROTOS -void yy_load_buffer_state( void ) -#else -void yy_load_buffer_state() -#endif - { - yy_n_chars = yy_current_buffer->yy_n_chars; - yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; - yyin = yy_current_buffer->yy_input_file; - yy_hold_char = *yy_c_buf_p; - } - - -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) -#else -YY_BUFFER_STATE yy_create_buffer( file, size ) -FILE *file; -int size; -#endif - { - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - yy_init_buffer( b, file ); - - return b; - } - - -#ifdef YY_USE_PROTOS -void yy_delete_buffer( YY_BUFFER_STATE b ) -#else -void yy_delete_buffer( b ) -YY_BUFFER_STATE b; -#endif - { - if ( ! b ) - return; - - if ( b == yy_current_buffer ) - yy_current_buffer = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - yy_flex_free( (void *) b->yy_ch_buf ); - - yy_flex_free( (void *) b ); - } - - -#ifndef YY_ALWAYS_INTERACTIVE -#ifndef YY_NEVER_INTERACTIVE -#include -#endif -#endif - -#ifdef YY_USE_PROTOS -void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) -#else -void yy_init_buffer( b, file ) -YY_BUFFER_STATE b; -FILE *file; -#endif - - - { - int oerrno = errno; - - yy_flush_buffer( b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - -#if defined(YY_ALWAYS_INTERACTIVE) && YY_ALWAYS_INTERACTIVE - b->yy_is_interactive = 1; -#else -#if defined(YY_NEVER_INTERACTIVE) && YY_NEVER_INTERACTIVE - b->yy_is_interactive = 0; -#else - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; -#endif -#endif - errno = oerrno; - } - - -#ifdef YY_USE_PROTOS -void yy_flush_buffer( YY_BUFFER_STATE b ) -#else -void yy_flush_buffer( b ) -YY_BUFFER_STATE b; -#endif - - { - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == yy_current_buffer ) - yy_load_buffer_state(); - } - - -#ifndef YY_NO_SCAN_BUFFER -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) -#else -YY_BUFFER_STATE yy_scan_buffer( base, size ) -char *base; -yy_size_t size; -#endif - { - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - yy_switch_to_buffer( b ); - - return b; - } -#endif - - -#ifndef YY_NO_SCAN_STRING -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) -#else -YY_BUFFER_STATE yy_scan_string( yy_str ) -yyconst char *yy_str; -#endif - { - int len; - for ( len = 0; yy_str[len]; ++len ) - ; - - return yy_scan_bytes( yy_str, len ); - } -#endif - - -#ifndef YY_NO_SCAN_BYTES -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) -#else -YY_BUFFER_STATE yy_scan_bytes( bytes, len ) -yyconst char *bytes; -int len; -#endif - { - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = len + 2; - buf = (char *) yy_flex_alloc( n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - - for ( i = 0; i < len; ++i ) - buf[i] = bytes[i]; - - buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; - - b = yy_scan_buffer( buf, n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; - } -#endif - - -#ifndef YY_NO_PUSH_STATE -#ifdef YY_USE_PROTOS -static void yy_push_state( int new_state ) -#else -static void yy_push_state( new_state ) -int new_state; -#endif - { - if ( yy_start_stack_ptr >= yy_start_stack_depth ) - { - yy_size_t new_size; - - yy_start_stack_depth += YY_START_STACK_INCR; - new_size = yy_start_stack_depth * sizeof( int ); - - if ( ! yy_start_stack ) - yy_start_stack = (int *) yy_flex_alloc( new_size ); - - else - yy_start_stack = (int *) yy_flex_realloc( - (void *) yy_start_stack, new_size ); - - if ( ! yy_start_stack ) - YY_FATAL_ERROR( - "out of memory expanding start-condition stack" ); - } - - yy_start_stack[yy_start_stack_ptr++] = YY_START; - - BEGIN(new_state); - } -#endif - - -#ifndef YY_NO_POP_STATE -static void yy_pop_state() - { - if ( --yy_start_stack_ptr < 0 ) - YY_FATAL_ERROR( "start-condition stack underflow" ); - - BEGIN(yy_start_stack[yy_start_stack_ptr]); - } -#endif - - -#ifndef YY_NO_TOP_STATE -static int yy_top_state() - { - return yy_start_stack[yy_start_stack_ptr - 1]; - } -#endif - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -#ifdef YY_USE_PROTOS -static void yy_fatal_error( yyconst char msg[] ) -#else -static void yy_fatal_error( msg ) -char msg[]; -#endif - { - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); - } - - - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - yytext[yyleng] = yy_hold_char; \ - yy_c_buf_p = yytext + n; \ - yy_hold_char = *yy_c_buf_p; \ - *yy_c_buf_p = '\0'; \ - yyleng = n; \ - } \ - while ( 0 ) - - -/* Internal utility routines. */ - -#ifndef yytext_ptr -#ifdef YY_USE_PROTOS -static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) -#else -static void yy_flex_strncpy( s1, s2, n ) -char *s1; -yyconst char *s2; -int n; -#endif - { - register int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; - } -#endif - -#ifdef YY_NEED_STRLEN -#ifdef YY_USE_PROTOS -static int yy_flex_strlen( yyconst char *s ) -#else -static int yy_flex_strlen( s ) -yyconst char *s; -#endif - { - register int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; - } -#endif - - -#ifdef YY_USE_PROTOS -static void *yy_flex_alloc( yy_size_t size ) -#else -static void *yy_flex_alloc( size ) -yy_size_t size; -#endif - { - return (void *) malloc( size ); - } - -#ifdef YY_USE_PROTOS -static void *yy_flex_realloc( void *ptr, yy_size_t size ) -#else -static void *yy_flex_realloc( ptr, size ) -void *ptr; -yy_size_t size; -#endif - { - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); - } - -#ifdef YY_USE_PROTOS -static void yy_flex_free( void *ptr ) -#else -static void yy_flex_free( ptr ) -void *ptr; -#endif - { - free( ptr ); - } - -#if defined(YY_MAIN) && YY_MAIN -int main() - { - yylex(); - return 0; - } -#endif -#line 449 "parse.lex" - -static void -_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); - if (dst == NULL) { - yyerror("unable to allocate memory"); - return; - } - yylval.string = dst; - - /* 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]; - } - dst[j] = '\0'; -} - -static void -append(src, len) - char *src; - int len; -{ - int olen = 0; - - if (yylval.string != NULL) - olen = strlen(yylval.string); - - _fill(src, len, olen); -} - -static void -fill_cmnd(s, len) - char *s; - int len; -{ - arg_len = arg_size = 0; - - yylval.command.cmnd = (char *) malloc(++len); - if (yylval.command.cmnd == NULL) { - yyerror("unable to allocate memory"); - return; - } - - /* copy the string and NULL-terminate it (escapes handled by fnmatch) */ - (void) strlcpy(yylval.command.cmnd, s, len); - - yylval.command.args = NULL; -} - -static void -fill_args(s, len, addspace) - char *s; - int len; - int addspace; -{ - int new_len; - char *p; - - if (yylval.command.args == NULL) { - addspace = 0; - new_len = len; - } else - new_len = arg_len + len + addspace; - - if (new_len >= arg_size) { - /* Allocate more space than we need for subsequent args */ - while (new_len >= (arg_size += COMMANDARGINC)) - ; - - p = yylval.command.args ? - (char *) realloc(yylval.command.args, arg_size) : - (char *) malloc(arg_size); - if (p == NULL) { - efree(yylval.command.args); - yyerror("unable to allocate memory"); - return; - } else - yylval.command.args = p; - } - - /* Efficiently append the arg (with a leading space if needed). */ - p = yylval.command.args + arg_len; - if (addspace) - *p++ = ' '; - if (strlcpy(p, s, arg_size - (p - yylval.command.args)) != len) - yyerror("fill_args: buffer overflow"); /* paranoia */ - arg_len = new_len; -} - -/* - * Check to make sure an IPv6 address does not contain multiple instances - * of the string "::". Assumes strlen(s) >= 1. - * Returns TRUE if address is valid else FALSE. - */ -static int -ipv6_valid(s) - const char *s; -{ - int nmatch = 0; - - for (; *s != '\0'; s++) { - if (s[0] == ':' && s[1] == ':') { - if (++nmatch > 1) - break; - } - if (s[0] == '/') - nmatch = 0; /* reset if we hit netmask */ - } - - return (nmatch <= 1); -} - -int -yywrap() -{ - - /* Free space used by the aliases unless called by testsudoers. */ - if (clearaliases) - reset_aliases(); - - return(TRUE); -} diff --git a/list.c b/list.c new file mode 100644 index 0000000..2e6482a --- /dev/null +++ b/list.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2007-2008 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. + */ + +#include + +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ + +#include "sudo.h" + +#ifndef lint +__unused static const char rcsid[] = "$Sudo: list.c,v 1.6 2008/11/09 14:13:12 millert Exp $"; +#endif /* lint */ + +struct list_proto { + struct list_proto *prev; + struct list_proto *next; +}; + +struct list_head_proto { + struct list_proto *first; + struct list_proto *last; +}; + +/* + * Pop the last element off the end of vh. + * Returns the popped element. + */ +void * +tq_pop(vh) + void *vh; +{ + struct list_head_proto *h = (struct list_head_proto *)vh; + void *last = NULL; + + if (!tq_empty(h)) { + last = (void *)h->last; + if (h->first == h->last) { + h->first = NULL; + h->last = NULL; + } else { + h->last = h->last->prev; + h->last->next = NULL; + } + } + return (last); +} + +/* + * Convert from a semi-circle queue to normal doubly-linked list + * with a head node. + */ +void +list2tq(vh, vl) + void *vh; + void *vl; +{ + struct list_head_proto *h = (struct list_head_proto *)vh; + struct list_proto *l = (struct list_proto *)vl; + + if (l != NULL) { +#ifdef DEBUG + if (l->prev == NULL) { + warningx("list2tq called with non-semicircular list"); + abort(); + } +#endif + h->first = l; + h->last = l->prev; /* l->prev points to the last member of l */ + l->prev = NULL; /* zero last ptr now that we have a head */ + } else { + h->first = NULL; + h->last = NULL; + } +} + +/* + * Append one queue (or single entry) to another using the + * circular properties of the prev pointer to simplify the logic. + */ +void +list_append(vl1, vl2) + void *vl1; + void *vl2; +{ + struct list_proto *l1 = (struct list_proto *)vl1; + struct list_proto *l2 = (struct list_proto *)vl2; + void *tail = l2->prev; + + l1->prev->next = l2; + l2->prev = l1->prev; + l1->prev = tail; +} + +/* + * Append the list of entries to the head node and convert + * e from a semi-circle queue to normal doubly-linked list. + */ +void +tq_append(vh, vl) + void *vh; + void *vl; +{ + struct list_head_proto *h = (struct list_head_proto *)vh; + struct list_proto *l = (struct list_proto *)vl; + void *tail = l->prev; + + if (h->first == NULL) + h->first = l; + else + h->last->next = l; + l->prev = h->last; + h->last = tail; +} diff --git a/list.h b/list.h new file mode 100644 index 0000000..ddf610a --- /dev/null +++ b/list.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2007 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. + * + * $Sudo: list.h,v 1.3 2007/09/11 19:42:48 millert Exp $ + */ + +#ifndef _SUDO_LIST_H +#define _SUDO_LIST_H + +/* + * Convenience macro for declaring a list head. + */ +#ifdef __STDC__ +#define TQ_DECLARE(n) \ +struct n##_list { \ + struct n *first; \ + struct n *last; \ +}; +#else +#define TQ_DECLARE(n) \ +struct n/**/_list { \ + struct n *first; \ + struct n *last; \ +}; +#endif + +/* + * Foreach loops: forward and reverse + */ +#undef tq_foreach_fwd +#define tq_foreach_fwd(h, v) \ + for ((v) = (h)->first; (v) != NULL; (v) = (v)->next) + +#undef tq_foreach_rev +#define tq_foreach_rev(h, v) \ + for ((v) = (h)->last; (v) != NULL; (v) = (v)->prev) + +/* + * Init a list head. + */ +#undef tq_init +#define tq_init(h) do { \ + (h)->first = NULL; \ + (h)->last = NULL; \ +} while (0) + +/* + * Simple macros to avoid exposing first/last and prev/next. + */ +#undef tq_empty +#define tq_empty(h) ((h)->first == NULL) + +#undef tq_first +#define tq_first(h) ((h)->first) + +#undef tq_last +#define tq_last(h) ((h)->last) + +#undef list_next +#define list_next(e) ((e)->next) + +#undef list_prev +#define list_prev(e) ((e)->prev) + +/* + * Prototypes for list.c + */ +void *tq_pop __P((void *)); +void tq_append __P((void *, void *)); +void list_append __P((void *, void *)); +void list2tq __P((void *, void *)); + +#endif /* _SUDO_LIST_H */ diff --git a/logging.c b/logging.c index 80d0f5a..b536305 100644 --- a/logging.c +++ b/logging.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994-1996,1998-2007 Todd C. Miller + * Copyright (c) 1994-1996, 1998-2008 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 @@ -48,12 +48,8 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include +#include #include #include #include @@ -62,15 +58,16 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: logging.c,v 1.168.2.16 2008/06/22 20:23:57 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: logging.c,v 1.203 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ static void do_syslog __P((int, char *)); static void do_logfile __P((char *)); static void send_mail __P((char *)); -static void mail_auth __P((int, char *)); +static int should_mail __P((int)); static char *get_timestr __P((void)); static void mysyslog __P((int, const char *, ...)); +static char *new_logline __P((const char *, int)); #define MAXSYSLOGTRIES 16 /* num of retries for broken syslogs */ @@ -273,56 +270,31 @@ do_logfile(msg) } /* - * Two main functions, log_error() to log errors and log_auth() to - * log allow/deny messages. + * Log and mail the denial message, optionally informing the user. */ void -log_auth(status, inform_user) +log_denial(status, inform_user) int status; int inform_user; { - char *evstr = NULL; char *message; char *logline; - int pri; - if (ISSET(status, VALIDATE_OK)) - pri = def_syslog_goodpri; - else - pri = def_syslog_badpri; - - /* Set error message, if any. */ - if (ISSET(status, VALIDATE_OK)) - message = ""; - else if (ISSET(status, FLAG_NO_USER)) - message = "user NOT in sudoers ; "; + /* Set error message. */ + if (ISSET(status, FLAG_NO_USER)) + message = "user NOT in sudoers"; else if (ISSET(status, FLAG_NO_HOST)) - message = "user NOT authorized on host ; "; - else if (ISSET(status, VALIDATE_NOT_OK)) - message = "command not allowed ; "; + message = "user NOT authorized on host"; else - message = "unknown error ; "; + message = "command not allowed"; - if (sudo_user.env_vars != NULL) { - size_t len = 7; /* " ; ENV=" */ - struct list_member *cur; - for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next) - len += strlen(cur->value) + 1; - evstr = emalloc(len); - strlcpy(evstr, " ; ENV=", len); - for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next) { - strlcat(evstr, cur->value, len); - strlcat(evstr, " ", len); /* NOTE: last one will fail */ - } - } - easprintf(&logline, "%sTTY=%s ; PWD=%s ; USER=%s%s ; COMMAND=%s%s%s", - message, user_tty, user_cwd, *user_runas, evstr ? evstr : "", - user_cmnd, user_args ? " " : "", user_args ? user_args : ""); + logline = new_logline(message, 0); - mail_auth(status, logline); /* send mail based on status */ + if (should_mail(status)) + send_mail(logline); /* send mail based on status */ /* Inform the user if they failed to authenticate. */ - if (inform_user && ISSET(status, VALIDATE_NOT_OK)) { + if (inform_user) { if (ISSET(status, FLAG_NO_USER)) (void) fprintf(stderr, "%s is not in the sudoers file. %s", user_name, "This incident will be reported.\n"); @@ -334,20 +306,47 @@ log_auth(status, inform_user) user_name, user_shost); else (void) fprintf(stderr, - "Sorry, user %s is not allowed to execute '%s%s%s' as %s on %s.\n", + "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n", user_name, user_cmnd, user_args ? " " : "", - user_args ? user_args : "", *user_runas, user_host); + user_args ? user_args : "", + list_pw ? list_pw->pw_name : runas_pw ? + runas_pw->pw_name : user_name, runas_gr ? ":" : "", + runas_gr ? runas_gr->gr_name : "", user_host); } /* * Log via syslog and/or a file. */ if (def_syslog) - do_syslog(pri, logline); + do_syslog(def_syslog_badpri, logline); + if (def_logfile) + do_logfile(logline); + + efree(logline); +} + +/* + * Log and potentially mail the allowed command. + */ +void +log_allowed(status) + int status; +{ + char *logline; + + logline = new_logline(NULL, 0); + + if (should_mail(status)) + send_mail(logline); /* send mail based on status */ + + /* + * Log via syslog and/or a file. + */ + if (def_syslog) + do_syslog(def_syslog_goodpri, logline); if (def_logfile) do_logfile(logline); - efree(evstr); efree(logline); } @@ -364,7 +363,6 @@ log_error(flags, fmt, va_alist) int serrno = errno; char *message; char *logline; - char *evstr = NULL; va_list ap; #ifdef __STDC__ va_start(ap, fmt); @@ -379,53 +377,21 @@ log_error(flags, fmt, va_alist) evasprintf(&message, fmt, ap); va_end(ap); - if (sudo_user.env_vars != NULL) { - size_t len = 7; /* " ; ENV=" */ - struct list_member *cur; - for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next) - len += strlen(cur->value) + 1; - evstr = emalloc(len); - strlcpy(evstr, " ; ENV=", len); - for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next) { - strlcat(evstr, cur->value, len); - strlcat(evstr, " ", len); /* NOTE: last one will fail */ - } - } - if (ISSET(flags, MSG_ONLY)) logline = message; - else if (ISSET(flags, USE_ERRNO)) { - if (user_args) { - easprintf(&logline, - "%s: %s ; TTY=%s ; PWD=%s ; USER=%s%s ; COMMAND=%s %s", - message, strerror(serrno), user_tty, user_cwd, *user_runas, - evstr ? evstr : "", user_cmnd, user_args); - } else { - easprintf(&logline, - "%s: %s ; TTY=%s ; PWD=%s ; USER=%s%s ; COMMAND=%s", message, - strerror(serrno), user_tty, user_cwd, *user_runas, - evstr ? evstr : "", user_cmnd); - } - } else { - if (user_args) { - easprintf(&logline, - "%s ; TTY=%s ; PWD=%s ; USER=%s%s ; COMMAND=%s %s", message, - user_tty, user_cwd, *user_runas, evstr ? evstr : "", - user_cmnd, user_args); - } else { - easprintf(&logline, - "%s ; TTY=%s ; PWD=%s ; USER=%s%s ; COMMAND=%s", message, - user_tty, user_cwd, *user_runas, evstr ? evstr : "", user_cmnd); - } - } + else + logline = new_logline(message, ISSET(flags, USE_ERRNO) ? serrno : 0); /* * Tell the user. */ - if (ISSET(flags, USE_ERRNO)) - warn("%s", message); - else - warnx("%s", message); + if (!ISSET(flags, NO_STDERR)) { + if (ISSET(flags, USE_ERRNO)) + warning("%s", message); + else + warningx("%s", message); + } + efree(message); /* * Send a copy of the error via mail. @@ -441,12 +407,13 @@ log_error(flags, fmt, va_alist) if (def_logfile) do_logfile(logline); - efree(message); if (logline != message) efree(logline); - if (!ISSET(flags, NO_EXIT)) + if (!ISSET(flags, NO_EXIT)) { + cleanup(0); exit(1); + } } #define MAX_MAILFLAGS 63 @@ -481,11 +448,11 @@ send_mail(line) /* Fork and return, child will daemonize. */ switch (pid = fork()) { case -1: - /* Error */ - err(1, "cannot fork"); + /* Error. */ + error(1, "cannot fork"); break; case 0: - /* Child */ + /* Child. */ switch (pid = fork()) { case -1: /* Error. */ @@ -500,7 +467,7 @@ send_mail(line) } break; default: - /* Parent */ + /* Parent. */ do { #ifdef HAVE_WAITPID rv = waitpid(pid, &status, 0); @@ -514,7 +481,7 @@ send_mail(line) /* Daemonize - disassociate from session/tty. */ #ifdef HAVE_SETSID if (setsid() == -1) - warn("setsid"); + warning("setsid"); #else setpgrp(0, 0); # ifdef TIOCNOTTY @@ -531,11 +498,13 @@ send_mail(line) (void) dup2(fd, STDERR_FILENO); } - /* Close password and other fds so we don't leak. */ - endpwent(); + /* Close password, group and other fds so we don't leak. */ + sudo_endpwent(); + sudo_endgrent(); closefrom(STDERR_FILENO + 1); /* Ignore SIGPIPE in case mailer exits prematurely (or is missing). */ + zero_bytes(&sa, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = SIG_IGN; @@ -601,9 +570,9 @@ send_mail(line) (void) close(pfd[0]); mail = fdopen(pfd[1], "w"); - /* Pipes are all setup, send message via sendmail. */ + /* Pipes are all setup, send message. */ (void) fprintf(mail, "To: %s\nFrom: %s\nAuto-Submitted: %s\nSubject: ", - def_mailto, user_name, "auto-generated"); + def_mailto, def_mailfrom ? def_mailfrom : user_name, "auto-generated"); for (p = def_mailsub; *p; p++) { /* Expand escapes in the subject */ if (*p == '%' && *(p+1) != '%') { @@ -626,40 +595,26 @@ send_mail(line) fclose(mail); do { #ifdef HAVE_WAITPID - rv = waitpid(pid, &status, 0); + rv = waitpid(pid, &status, 0); #else - rv = wait(&status); + rv = wait(&status); #endif } while (rv == -1 && errno == EINTR); _exit(0); } /* - * Send mail based on the value of "status" and compile-time options. + * Determine whether we should send mail based on "status" and defaults options. */ -static void -mail_auth(status, line) +static int +should_mail(status) int status; - char *line; { - int mail_mask; - - /* If any of these bits are set in status, we send mail. */ - if (def_mail_always) - mail_mask = - VALIDATE_ERROR|VALIDATE_OK|FLAG_NO_USER|FLAG_NO_HOST|VALIDATE_NOT_OK; - else { - mail_mask = VALIDATE_ERROR; - if (def_mail_no_user) - SET(mail_mask, FLAG_NO_USER); - if (def_mail_no_host) - SET(mail_mask, FLAG_NO_HOST); - if (def_mail_no_perms) - SET(mail_mask, VALIDATE_NOT_OK); - } - if ((status & mail_mask) != 0) - send_mail(line); + return(def_mail_always || ISSET(status, VALIDATE_ERROR) || + (def_mail_no_user && ISSET(status, FLAG_NO_USER)) || + (def_mail_no_host && ISSET(status, FLAG_NO_HOST)) || + (def_mail_no_perms && !ISSET(status, VALIDATE_OK))); } /* @@ -696,3 +651,112 @@ get_timestr() return(s); } + +#define LL_TTY_STR "TTY=" +#define LL_CWD_STR "PWD=" /* XXX - should be CWD= */ +#define LL_USER_STR "USER=" +#define LL_GROUP_STR "GROUP=" +#define LL_ENV_STR "ENV=" +#define LL_CMND_STR "COMMAND=" + +/* + * Allocate and fill in a new logline. + */ +static char * +new_logline(message, serrno) + const char *message; + int serrno; +{ + size_t len = 0; + char *evstr = NULL; + char *errstr = NULL; + char *line; + + /* + * Compute line length + */ + if (message != NULL) + len += strlen(message) + 3; + if (serrno) { + errstr = strerror(serrno); + len += strlen(errstr) + 3; + } + len += sizeof(LL_TTY_STR) + 2 + strlen(user_tty); + len += sizeof(LL_CWD_STR) + 2 + strlen(user_cwd); + if (runas_pw != NULL) + len += sizeof(LL_USER_STR) + 2 + strlen(runas_pw->pw_name); + if (runas_gr != NULL) + len += sizeof(LL_GROUP_STR) + 2 + strlen(runas_gr->gr_name); + if (sudo_user.env_vars != NULL) { + size_t evlen = 0; + struct list_member *cur; + for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next) + evlen += strlen(cur->value) + 1; + evstr = emalloc(evlen); + evstr[0] = '\0'; + for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next) { + strlcat(evstr, cur->value, evlen); + strlcat(evstr, " ", evlen); /* NOTE: last one will fail */ + } + len += sizeof(LL_ENV_STR) + 2 + evlen; + } + len += sizeof(LL_CMND_STR) - 1 + strlen(user_cmnd); + if (user_args != NULL) + len += strlen(user_args) + 1; + + /* + * Allocate and build up the line. + */ + line = emalloc(++len); + line[0] = '\0'; + + if (message != NULL) { + if (strlcat(line, message, len) >= len || + strlcat(line, errstr ? " : " : " ; ", len) >= len) + goto toobig; + } + if (serrno) { + if (strlcat(line, errstr, len) >= len || + strlcat(line, " ; ", len) >= len) + goto toobig; + } + if (strlcat(line, LL_TTY_STR, len) >= len || + strlcat(line, user_tty, len) >= len || + strlcat(line, " ; ", len) >= len) + goto toobig; + if (strlcat(line, LL_CWD_STR, len) >= len || + strlcat(line, user_cwd, len) >= len || + strlcat(line, " ; ", len) >= len) + goto toobig; + if (runas_pw != NULL) { + if (strlcat(line, LL_USER_STR, len) >= len || + strlcat(line, runas_pw->pw_name, len) >= len || + strlcat(line, " ; ", len) >= len) + goto toobig; + } + if (runas_gr != NULL) { + if (strlcat(line, LL_GROUP_STR, len) >= len || + strlcat(line, runas_gr->gr_name, len) >= len || + strlcat(line, " ; ", len) >= len) + goto toobig; + } + if (evstr != NULL) { + if (strlcat(line, LL_ENV_STR, len) >= len || + strlcat(line, evstr, len) >= len || + strlcat(line, " ; ", len) >= len) + goto toobig; + efree(evstr); + } + if (strlcat(line, LL_CMND_STR, len) >= len || + strlcat(line, user_cmnd, len) >= len) + goto toobig; + if (user_args != NULL) { + if (strlcat(line, " ", len) >= len || + strlcat(line, user_args, len) >= len) + goto toobig; + } + + return (line); +toobig: + errorx(1, "internal error: insufficient space for log line"); +} diff --git a/logging.h b/logging.h index 77196fa..b3f4941 100644 --- a/logging.h +++ b/logging.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 1999, 2004 Todd C. Miller + * Copyright (c) 1999-2005, 2008 + * 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 @@ -12,6 +13,8 @@ * 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. + * + * $Sudo: logging.h,v 1.13 2008/11/09 14:13:12 millert Exp $ */ #ifndef _LOGGING_H @@ -34,6 +37,7 @@ #define USE_ERRNO 0x02 #define NO_MAIL 0x04 #define NO_EXIT 0x08 +#define NO_STDERR 0x10 /* * Maximum number of characters to log per entry. The syslogger @@ -45,7 +49,8 @@ # define MAXSYSLOGLEN 960 #endif -void log_auth __P((int, int)); +void log_allowed __P((int)); +void log_denial __P((int, int)); void log_error __P((int flags, const char *fmt, ...)) __printflike(2, 3); RETSIGTYPE reapchild __P((int)); diff --git a/lsearch.c b/lsearch.c deleted file mode 100644 index fa3f491..0000000 --- a/lsearch.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Roger L. Snyder. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ - -#include -#include "emul/search.h" - -#if defined(LIBC_SCCS) && !defined(lint) -static const char sccsid[] = "@(#)lsearch.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#ifndef lint -__unused static const char rcsid[] = "$Sudo: lsearch.c,v 1.18.4.1 2007/06/12 00:56:42 millert Exp $"; -#endif /* lint */ - -typedef int (*cmp_fn_t) __P((const VOID *, const VOID *)); -static VOID *linear_base __P((const VOID *, const VOID *, size_t *, size_t, - cmp_fn_t, int)); - -VOID * -lsearch(key, base, nelp, width, compar) - const VOID *key, *base; - size_t *nelp, width; - cmp_fn_t compar; -{ - return(linear_base(key, base, nelp, width, compar, 1)); -} - -VOID * -lfind(key, base, nelp, width, compar) - const VOID *key, *base; - size_t *nelp, width; - cmp_fn_t compar; -{ - return(linear_base(key, base, nelp, width, compar, 0)); -} - -static VOID * -linear_base(key, base, nelp, width, compar, add_flag) - const VOID *key, *base; - size_t *nelp, width; - cmp_fn_t compar; - int add_flag; -{ - /* Strict ANSI does not allow pointer arithmetic on void *'s */ - const char *element, *end; - - end = (const char *) base + *nelp * width; - for (element = (const char *) base; element < end; element += width) - if (!compar(key, (VOID *) element)) /* key found */ - return((VOID *) element); - if (!add_flag) /* key not found */ - return(NULL); - - /* - * The UNIX System User's Manual, 1986 edition claims that - * a NULL pointer is returned by lsearch with errno set - * appropriately, if there is not enough room in the table - * to add a new item. This can't be done as none of these - * routines have any method of determining the size of the - * table. This comment was isn't in the 1986-87 System V - * manual. - */ - ++*nelp; - (void) memcpy((VOID *)end, key, width); - return((VOID *) end); -} diff --git a/match.c b/match.c new file mode 100644 index 0000000..b3b7f9a --- /dev/null +++ b/match.c @@ -0,0 +1,845 @@ +/* + * Copyright (c) 1996, 1998-2005, 2007-2008 + * 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. + * + * 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. + */ + +#include + +#include +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_FNMATCH +# include +#endif /* HAVE_FNMATCH */ +#ifdef HAVE_EXTENDED_GLOB +# include +#endif /* HAVE_EXTENDED_GLOB */ +#ifdef HAVE_NETGROUP_H +# include +#endif /* HAVE_NETGROUP_H */ +#include +#include +#include +#include +#include +#include +#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 "sudo.h" +#include "interfaces.h" +#include "parse.h" +#include + +#ifndef HAVE_FNMATCH +# include "emul/fnmatch.h" +#endif /* HAVE_FNMATCH */ +#ifndef HAVE_EXTENDED_GLOB +# include "emul/glob.h" +#endif /* HAVE_EXTENDED_GLOB */ + +#ifndef lint +__unused static const char rcsid[] = "$Sudo: match.c,v 1.38 2008/11/02 14:35:37 millert Exp $"; +#endif /* lint */ + +static struct member_list empty; + +static int command_matches_dir __P((char *, size_t)); + +/* + * Returns TRUE if string 's' contains meta characters. + */ +#define has_meta(s) (strpbrk(s, "\\?*[]") != NULL) + +/* + * Check for user described by pw in a list of members. + * Returns ALLOW, DENY or UNSPEC. + */ +static int +_userlist_matches(pw, list) + struct passwd *pw; + struct member_list *list; +{ + struct member *m; + struct alias *a; + int rval, matched = UNSPEC; + + tq_foreach_rev(list, m) { + switch (m->type) { + case ALL: + matched = !m->negated; + break; + case NETGROUP: + if (netgr_matches(m->name, NULL, NULL, pw->pw_name)) + matched = !m->negated; + break; + case USERGROUP: + if (usergr_matches(m->name, pw->pw_name, pw)) + matched = !m->negated; + break; + case ALIAS: + if ((a = find_alias(m->name, USERALIAS)) != NULL) { + rval = _userlist_matches(pw, &a->members); + if (rval != UNSPEC) + matched = m->negated ? !rval : rval; + break; + } + /* FALLTHROUGH */ + case WORD: + if (userpw_matches(m->name, pw->pw_name, pw)) + matched = !m->negated; + break; + } + if (matched != UNSPEC) + break; + } + return(matched); +} + +int +userlist_matches(pw, list) + struct passwd *pw; + struct member_list *list; +{ + alias_seqno++; + return(_userlist_matches(pw, list)); +} + +/* + * Check for user described by pw in a list of members. + * If both lists are empty compare against def_runas_default. + * Returns ALLOW, DENY or UNSPEC. + */ +static int +_runaslist_matches(user_list, group_list) + struct member_list *user_list; + struct member_list *group_list; +{ + struct member *m; + 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 (tq_empty(user_list) && tq_empty(group_list)) + return(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw)); + + if (runas_pw != NULL) { + tq_foreach_rev(user_list, m) { + switch (m->type) { + case ALL: + matched = !m->negated; + break; + case NETGROUP: + if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name)) + matched = !m->negated; + break; + case USERGROUP: + if (usergr_matches(m->name, runas_pw->pw_name, runas_pw)) + matched = !m->negated; + break; + case ALIAS: + if ((a = find_alias(m->name, RUNASALIAS)) != NULL) { + rval = _runaslist_matches(&a->members, &empty); + if (rval != UNSPEC) + matched = m->negated ? !rval : rval; + break; + } + /* FALLTHROUGH */ + case WORD: + if (userpw_matches(m->name, runas_pw->pw_name, runas_pw)) + matched = !m->negated; + break; + } + if (matched != UNSPEC) + break; + } + } + + if (runas_gr != NULL) { + tq_foreach_rev(group_list, m) { + switch (m->type) { + case ALL: + matched = !m->negated; + break; + case ALIAS: + if ((a = find_alias(m->name, RUNASALIAS)) != NULL) { + rval = _runaslist_matches(&a->members, &empty); + if (rval != UNSPEC) + matched = m->negated ? !rval : rval; + break; + } + /* FALLTHROUGH */ + case WORD: + if (group_matches(m->name, runas_gr)) + matched = !m->negated; + break; + } + if (matched != UNSPEC) + break; + } + } + + return(matched); +} + +int +runaslist_matches(user_list, group_list) + struct member_list *user_list; + struct member_list *group_list; +{ + alias_seqno++; + return(_runaslist_matches(user_list ? user_list : &empty, + group_list ? group_list : &empty)); +} + +/* + * Check for host and shost in a list of members. + * Returns ALLOW, DENY or UNSPEC. + */ +static int +_hostlist_matches(list) + struct member_list *list; +{ + struct member *m; + struct alias *a; + int rval, matched = UNSPEC; + + tq_foreach_rev(list, m) { + switch (m->type) { + case ALL: + matched = !m->negated; + break; + case NETGROUP: + if (netgr_matches(m->name, user_host, user_shost, NULL)) + matched = !m->negated; + break; + case NTWKADDR: + if (addr_matches(m->name)) + matched = !m->negated; + break; + case ALIAS: + if ((a = find_alias(m->name, HOSTALIAS)) != NULL) { + rval = _hostlist_matches(&a->members); + if (rval != UNSPEC) + matched = m->negated ? !rval : rval; + break; + } + /* FALLTHROUGH */ + case WORD: + if (hostname_matches(user_shost, user_host, m->name)) + matched = !m->negated; + break; + } + if (matched != UNSPEC) + break; + } + return(matched); +} + +int +hostlist_matches(list) + struct member_list *list; +{ + alias_seqno++; + return(_hostlist_matches(list)); +} + +/* + * Check for cmnd and args in a list of members. + * Returns ALLOW, DENY or UNSPEC. + */ +static int +_cmndlist_matches(list) + struct member_list *list; +{ + struct member *m; + int rval, matched = UNSPEC; + + tq_foreach_rev(list, m) { + rval = cmnd_matches(m); + if (rval != UNSPEC) { + matched = m->negated ? !rval : rval; + break; + } + } + return(matched); +} + +int +cmndlist_matches(list) + struct member_list *list; +{ + alias_seqno++; + return(_cmndlist_matches(list)); +} + +/* + * Check cmnd and args. + * Returns ALLOW, DENY or UNSPEC. + */ +int +cmnd_matches(m) + struct member *m; +{ + struct alias *a; + struct sudo_command *c; + int rval, matched = UNSPEC; + + switch (m->type) { + case ALL: + matched = !m->negated; + break; + case ALIAS: + alias_seqno++; + if ((a = find_alias(m->name, CMNDALIAS)) != NULL) { + rval = _cmndlist_matches(&a->members); + if (rval != UNSPEC) + matched = m->negated ? !rval : rval; + } + break; + case COMMAND: + c = (struct sudo_command *)m->name; + if (command_matches(c->cmnd, c->args)) + matched = !m->negated; + break; + } + return(matched); +} + +/* + * If path doesn't end in /, return TRUE iff cmnd & path name the same inode; + * otherwise, return TRUE if user_cmnd names one of the inodes in path. + */ +int +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) { + /* + * Return true if both sudoers_cmnd and user_cmnd are "sudoedit" 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 (strcmp(sudoers_cmnd, "sudoedit") != 0 || + strcmp(user_cmnd, "sudoedit") != 0) + 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); + } 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. + */ +#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; + } + + /* 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); + + 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); + } else { + /* If it ends in '/' it is a directory spec. */ + 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); + } +} + +/* + * Return TRUE if user_cmnd names one of the inodes in dir, else FALSE. + */ +static int +command_matches_dir(sudoers_dir, dlen) + char *sudoers_dir; + size_t dlen; +{ + struct stat sudoers_stat; + struct dirent *dent; + char buf[PATH_MAX]; + DIR *dirp; + + /* + * Grot through directory entries, looking for user_base. + */ + dirp = opendir(sudoers_dir); + if (dirp == NULL) + return(FALSE); + + if (strlcpy(buf, sudoers_dir, sizeof(buf)) >= sizeof(buf)) + return(FALSE); + while ((dent = readdir(dirp)) != NULL) { + /* ignore paths > PATH_MAX (XXX - log) */ + buf[dlen] = '\0'; + if (strlcat(buf, dent->d_name, sizeof(buf)) >= sizeof(buf)) + continue; + + /* only stat if basenames are the same */ + if (strcmp(user_base, dent->d_name) != 0 || + stat(buf, &sudoers_stat) == -1) + continue; + if (user_stat->st_dev == sudoers_stat.st_dev && + user_stat->st_ino == sudoers_stat.st_ino) { + efree(safe_cmnd); + safe_cmnd = estrdup(buf); + break; + } + } + + closedir(dirp); + return(dent != NULL); +} + +static int +addr_matches_if(n) + char *n; +{ + int i; + struct in_addr addr; + struct interface *ifp; +#ifdef HAVE_IN6_ADDR + struct in6_addr addr6; + int j; +#endif + int family; + +#ifdef HAVE_IN6_ADDR + if (inet_pton(AF_INET6, n, &addr6) > 0) { + family = AF_INET6; + } else +#endif + { + family = AF_INET; + addr.s_addr = inet_addr(n); + } + + for (i = 0; i < num_interfaces; i++) { + ifp = &interfaces[i]; + if (ifp->family != family) + continue; + switch(family) { + case AF_INET: + if (ifp->addr.ip4.s_addr == addr.s_addr || + (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr) + == addr.s_addr) + return(TRUE); + break; +#ifdef HAVE_IN6_ADDR + case AF_INET6: + if (memcmp(ifp->addr.ip6.s6_addr, addr6.s6_addr, + sizeof(addr6.s6_addr)) == 0) + return(TRUE); + for (j = 0; j < sizeof(addr6.s6_addr); j++) { + if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr6.s6_addr[j]) + break; + } + if (j == sizeof(addr6.s6_addr)) + return(TRUE); +#endif + } + } + + return(FALSE); +} + +static int +addr_matches_if_netmask(n, m) + char *n; + char *m; +{ + int i; + struct in_addr addr, mask; + struct interface *ifp; +#ifdef HAVE_IN6_ADDR + struct in6_addr addr6, mask6; + int j; +#endif + int family; + +#ifdef HAVE_IN6_ADDR + if (inet_pton(AF_INET6, n, &addr6) > 0) + family = AF_INET6; + else +#endif + { + family = AF_INET; + addr.s_addr = inet_addr(n); + } + + if (family == AF_INET) { + if (strchr(m, '.')) + mask.s_addr = inet_addr(m); + else { + i = 32 - atoi(m); + mask.s_addr = 0xffffffff; + mask.s_addr >>= i; + mask.s_addr <<= i; + mask.s_addr = htonl(mask.s_addr); + } + } +#ifdef HAVE_IN6_ADDR + else { + if (inet_pton(AF_INET6, m, &mask6) <= 0) { + j = atoi(m); + for (i = 0; i < 16; i++) { + if (j < i * 8) + mask6.s6_addr[i] = 0; + else if (i * 8 + 8 <= j) + mask6.s6_addr[i] = 0xff; + else + mask6.s6_addr[i] = 0xff00 >> (j - i * 8); + } + } + } +#endif /* HAVE_IN6_ADDR */ + + for (i = 0; i < num_interfaces; i++) { + ifp = &interfaces[i]; + if (ifp->family != family) + continue; + switch(family) { + case AF_INET: + if ((ifp->addr.ip4.s_addr & mask.s_addr) == addr.s_addr) + return(TRUE); +#ifdef HAVE_IN6_ADDR + case AF_INET6: + for (j = 0; j < sizeof(addr6.s6_addr); j++) { + if ((ifp->addr.ip6.s6_addr[j] & mask6.s6_addr[j]) != addr6.s6_addr[j]) + break; + } + if (j == sizeof(addr6.s6_addr)) + return(TRUE); +#endif /* HAVE_IN6_ADDR */ + } + } + + return(FALSE); +} + +/* + * Returns TRUE if "n" is one of our ip addresses or if + * "n" is a network that we are on, else returns FALSE. + */ +int +addr_matches(n) + char *n; +{ + char *m; + int retval; + + /* If there's an explicit netmask, use it. */ + if ((m = strchr(n, '/'))) { + *m++ = '\0'; + retval = addr_matches_if_netmask(n, m); + *(m - 1) = '/'; + } else + retval = addr_matches_if(n); + + return(retval); +} + +/* + * Returns TRUE if the hostname matches the pattern, else FALSE + */ +int +hostname_matches(shost, lhost, pattern) + char *shost; + char *lhost; + char *pattern; +{ + if (has_meta(pattern)) { + if (strchr(pattern, '.')) + return(!fnmatch(pattern, lhost, FNM_CASEFOLD)); + else + return(!fnmatch(pattern, shost, FNM_CASEFOLD)); + } else { + if (strchr(pattern, '.')) + return(!strcasecmp(lhost, pattern)); + else + return(!strcasecmp(shost, pattern)); + } +} + +/* + * Returns TRUE if the user/uid from sudoers matches the specified user/uid, + * else returns FALSE. + */ +int +userpw_matches(sudoers_user, user, pw) + char *sudoers_user; + char *user; + struct passwd *pw; +{ + if (pw != NULL && *sudoers_user == '#') { + uid_t uid = (uid_t) atoi(sudoers_user + 1); + if (uid == pw->pw_uid) + return(TRUE); + } + return(strcmp(sudoers_user, user) == 0); +} + +/* + * Returns TRUE if the group/gid from sudoers matches the specified group/gid, + * else returns FALSE. + */ +int +group_matches(sudoers_group, gr) + char *sudoers_group; + struct group *gr; +{ + if (*sudoers_group == '#') { + gid_t gid = (gid_t) atoi(sudoers_group + 1); + if (gid == gr->gr_gid) + return(TRUE); + } + return(strcmp(gr->gr_name, sudoers_group) == 0); +} + +/* + * 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) + char *group; + char *user; + struct passwd *pw; +{ + struct group *grp; + char **cur; + int i; + + /* make sure we have a valid usergroup, sudo style */ + if (*group++ != '%') + return(FALSE); + + /* 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); + + /* check against user's primary (passwd file) gid */ + if (grp->gr_gid == pw->pw_gid) + return(TRUE); + + /* + * If we are matching the invoking or list user and that user has a + * supplementary group vector, check it first. + */ + if (strcmp(user, list_pw ? list_pw->pw_name : user_name) == 0) { + for (i = 0; i < user_ngroups; i++) + if (grp->gr_gid == user_groups[i]) + return(TRUE); + } + if (grp->gr_mem != NULL) { + for (cur = grp->gr_mem; *cur; cur++) + if (strcmp(*cur, user) == 0) + return(TRUE); + } + + return(FALSE); +} + +/* + * Returns TRUE if "host" and "user" belong to the netgroup "netgr", + * else return FALSE. Either of "host", "shost" or "user" may be NULL + * in which case that argument is not checked... + * + * XXX - swap order of host & shost + */ +int +netgr_matches(netgr, lhost, shost, user) + char *netgr; + char *lhost; + char *shost; + char *user; +{ + static char *domain; +#ifdef HAVE_GETDOMAINNAME + static int initialized; +#endif + + /* make sure we have a valid netgroup, sudo style */ + if (*netgr++ != '+') + return(FALSE); + +#ifdef HAVE_GETDOMAINNAME + /* get the domain name (if any) */ + if (!initialized) { + domain = (char *) emalloc(MAXHOSTNAMELEN + 1); + if (getdomainname(domain, MAXHOSTNAMELEN + 1) == -1 || *domain == '\0') { + efree(domain); + domain = NULL; + } + initialized = 1; + } +#endif /* HAVE_GETDOMAINNAME */ + +#ifdef HAVE_INNETGR + if (innetgr(netgr, lhost, user, domain)) + return(TRUE); + else if (lhost != shost && innetgr(netgr, shost, user, domain)) + return(TRUE); +#endif /* HAVE_INNETGR */ + + return(FALSE); +} diff --git a/memrchr.c b/memrchr.c index 7d0554d..f66f8a0 100644 --- a/memrchr.c +++ b/memrchr.c @@ -19,7 +19,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: memrchr.c,v 1.1.2.3 2007/11/27 17:06:54 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: memrchr.c,v 1.4 2007/11/27 17:13:03 millert Exp $"; #endif /* lint */ #include @@ -29,9 +29,9 @@ __unused static const char rcsid[] = "$Sudo: memrchr.c,v 1.1.2.3 2007/11/27 17:0 * Reverse memchr() * Find the last occurrence of 'c' in the buffer 's' of size 'n'. */ -VOID * +void * memrchr(s, c, n) - const VOID *s; + const void *s; int c; size_t n; { @@ -41,8 +41,8 @@ memrchr(s, c, n) cp = (unsigned char *)s + n; do { if (*(--cp) == (unsigned char)c) - return((VOID *)cp); + return((void *)cp); } while (--n != 0); } - return((VOID *)0); + return((void *)0); } diff --git a/mkstemp.c b/mkstemp.c index 71126f8..1c9b6d4 100644 --- a/mkstemp.c +++ b/mkstemp.c @@ -1,44 +1,25 @@ -/* $OpenBSD: mktemp.c,v 1.19 2005/08/08 08:05:36 espie Exp $ */ - /* - * Copyright (c) 2000, 2001, 2005 Todd C. Miller - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. + * Copyright (c) 2001, 2003, 2008 Todd C. Miller * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * 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. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "config.h" #include #include -#if defined(TIME_WITH_SYS_TIME) || defined(HAVE_SYS_TIME_H) -# include -#endif -#include #include +#include #include #ifdef HAVE_STDLIB_H # include @@ -51,7 +32,7 @@ #include "sudo.h" #ifndef lint -static const char rcsid[] = "$Sudo: mkstemp.c,v 1.1.2.1 2007/06/12 17:06:20 millert Exp $"; +static const char rcsid[] = "$Sudo: mkstemp.c,v 1.2 2008/08/20 11:40:15 millert Exp $"; #endif /* not lint */ static unsigned int get_random __P((void)); @@ -61,98 +42,31 @@ int mkstemp(path) char *path; { - char *start, *trv; - struct stat sbuf; - int fd, rval; - pid_t pid; + char *start, *cp; + int fd, r; char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; if (*path == '\0') { errno = EINVAL; - return (-1); /* zero length path */ - } - pid = getpid(); - for (trv = path; *trv; ++trv) - ; - --trv; - while (trv >= path && *trv == 'X' && pid != 0) { - *trv-- = (pid % 10) + '0'; - pid /= 10; - } - while (trv >= path && *trv == 'X') { - char c; - - /* assumes pid_t is at least 16 bits */ - pid = (get_random() & 0xffff) % (26 + 26); - c = alphabet[pid]; - *trv-- = c; + return(0); } - start = trv + 1; - /* - * check the target directory; if you have six X's and it - * doesn't exist this runs for a *very* long time. - */ - for (;; --trv) { - if (trv <= path) - break; - if (*trv == '/') { - *trv = '\0'; - rval = stat(path, &sbuf); - *trv = '/'; - if (rval != 0) - return (-1); - if (!S_ISDIR(sbuf.st_mode)) { - errno = ENOTDIR; - return (-1); - } - break; - } - } + for (cp = path; *cp; cp++) + ; + do { + cp--; + } while (cp >= path && *cp == 'X'); + start = cp + 1; for (;;) { - if ((fd = open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) - return (fd); - if (errno != EEXIST) - return (-1); - - /* tricky little algorithm for backward compatibility */ - for (trv = start;;) { - if (!*trv) - return (-1); - if (*trv == 'Z') - *trv++ = 'a'; - else { - if (isdigit((unsigned char)(*trv))) - *trv = 'a'; - else if (*trv == 'z') /* wrap from z to A */ - *trv = 'A'; - else { -#ifdef HAVE_EBCDIC - switch(*trv) { - case 'i': - *trv = 'j'; - break; - case 'r': - *trv = 's'; - break; - case 'I': - *trv = 'J'; - break; - case 'R': - *trv = 'S'; - break; - default: - ++*trv; - break; - } -#else - ++*trv; -#endif - } - break; - } + for (cp = start; *cp; cp++) { + r = get_random % (26 + 26); + *cp = alphabet[r]; } + + fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); + if (fd != -1 || errno != EEXIST) + return(fd); } /*NOTREACHED*/ } diff --git a/parse.c b/parse.c index 8c4a1e5..ef4a495 100644 --- a/parse.c +++ b/parse.c @@ -1,6 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007 - * Todd C. Miller + * Copyright (c) 2004-2005, 2007-2008 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 @@ -15,18 +14,12 @@ * 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. - * - * 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. */ #include #include #include -#include -#include #include #ifdef STDC_HEADERS # include @@ -46,651 +39,628 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_FNMATCH -# include -#endif /* HAVE_FNMATCH */ -#ifdef HAVE_EXTENDED_GLOB -# include -#endif /* HAVE_EXTENDED_GLOB */ -#ifdef HAVE_NETGROUP_H -# include -#endif /* HAVE_NETGROUP_H */ #include #include #include -#include -#include -#include -#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 "sudo.h" #include "parse.h" -#include "interfaces.h" - -#ifndef HAVE_FNMATCH -# include "emul/fnmatch.h" -#endif /* HAVE_FNMATCH */ -#ifndef HAVE_EXTENDED_GLOB -# include "emul/glob.h" -#endif /* HAVE_EXTENDED_GLOB */ +#include "lbuf.h" +#include #ifndef lint -__unused static const char rcsid[] = "$Sudo: parse.c,v 1.160.2.16 2008/02/09 14:44:48 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: parse.c,v 1.238 2008/12/09 13:49:55 millert Exp $"; #endif /* lint */ -/* - * Globals - */ -int parse_error = FALSE; -extern int keepall; -extern FILE *yyin, *yyout; +/* Characters that must be quoted in sudoers */ +#define SUDOERS_QUOTED ":\\,=#\"" + +/* sudoers nsswitch routines */ +struct sudo_nss sudo_nss_file = { + &sudo_nss_file, + NULL, + sudo_file_open, + sudo_file_close, + sudo_file_parse, + sudo_file_setdefs, + sudo_file_lookup, + sudo_file_display_cmnd, + sudo_file_display_defaults, + sudo_file_display_bound_defaults, + sudo_file_display_privs +}; /* - * Prototypes + * Parser externs. */ -static int has_meta __P((char *)); - void init_parser __P((void)); +extern FILE *yyin; +extern char *errorfile; +extern int errorlineno, parse_error; /* - * Look up the user in the sudoers file and check to see if they are - * allowed to run the specified command on this host as the target user. + * Local prototypes. */ +static void print_member __P((struct lbuf *, char *, int, int, int)); +static int display_bound_defaults __P((int, struct lbuf *)); + int -sudoers_lookup(pwflag) - int pwflag; +sudo_file_open(nss) + struct sudo_nss *nss; { - int error, nopass; - - /* We opened _PATH_SUDOERS in check_sudoers() so just rewind it. */ - rewind(sudoers_fp); - yyin = sudoers_fp; - yyout = stdout; + if (def_ignore_local_sudoers) + return(-1); + nss->handle = open_sudoers(_PATH_SUDOERS, NULL); + return(nss->handle ? 0 : -1); +} - /* Allocate space for data structures in the parser. */ - init_parser(); +int +sudo_file_close(nss) + struct sudo_nss *nss; +{ + /* Free parser data structures and close sudoers file. */ + init_parser(NULL, 0); + if (nss->handle != NULL) { + fclose(nss->handle); + nss->handle = NULL; + yyin = NULL; + } + return(0); +} - /* Keep more state for pseudo-commands so that listpw and verifypw work */ - if (pwflag > 0) - keepall = TRUE; +/* + * Parse the specified sudoers file. + */ +int +sudo_file_parse(nss) + struct sudo_nss *nss; +{ + if (nss->handle == NULL) + return(-1); + + init_parser(_PATH_SUDOERS, 0); + yyin = nss->handle; + if (yyparse() != 0 || parse_error) { + log_error(NO_EXIT, "parse error in %s near line %d", + errorfile, errorlineno); + return(-1); + } + return(0); +} - /* Need to be runas user while stat'ing things in the parser. */ - set_perms(PERM_RUNAS); - error = yyparse(); +/* + * Wrapper around update_defaults() for nsswitch code. + */ +int +sudo_file_setdefs(nss) + struct sudo_nss *nss; +{ + if (nss->handle == NULL) + return(-1); - /* Close the sudoers file now that we are done with it. */ - (void) fclose(sudoers_fp); - sudoers_fp = NULL; + if (!update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER)) + return(-1); + return(0); +} - if (error || parse_error) { - set_perms(PERM_ROOT); - return(VALIDATE_ERROR); - } +/* + * Look up the user in the parsed sudoers file and check to see if they are + * allowed to run the specified command on this host as the target user. + */ +int +sudo_file_lookup(nss, validated, pwflag) + struct sudo_nss *nss; + int validated; + int pwflag; +{ + int match, host_match, runas_match, cmnd_match; + struct cmndspec *cs; + struct cmndtag *tags = NULL; + struct privilege *priv; + struct userspec *us; - /* - * Assume the worst. If the stack is empty the user was - * not mentioned at all. - */ - if (def_authenticate) - error = VALIDATE_NOT_OK; - else - error = VALIDATE_NOT_OK | FLAG_NOPASS; - if (pwflag) { - SET(error, FLAG_NO_CHECK); - } else { - SET(error, FLAG_NO_HOST); - if (!top) - SET(error, FLAG_NO_USER); - } + if (nss->handle == NULL) + return(validated); /* * Only check the actual command if pwflag is not set. * It is set for the "validate", "list" and "kill" pseudo-commands. * Always check the host and user. */ - nopass = -1; if (pwflag) { - int found; + int nopass; enum def_tupple pwcheck; pwcheck = (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple; - - if (pwcheck == always && def_authenticate) - nopass = FLAG_CHECK_USER; - else if (pwcheck == never || !def_authenticate) - nopass = FLAG_NOPASS; - found = 0; - while (top) { - if (host_matches == TRUE) { - found = 1; - if (pwcheck == any && no_passwd == TRUE) - nopass = FLAG_NOPASS; - else if (pwcheck == all && nopass != 0) - nopass = (no_passwd == TRUE) ? FLAG_NOPASS : 0; - } - top--; - } - if (found) { - set_perms(PERM_ROOT); - if (nopass == -1) - nopass = 0; - return(VALIDATE_OK | nopass); - } - } else { - while (top) { - if (host_matches == TRUE) { - CLR(error, FLAG_NO_HOST); - if (runas_matches == TRUE && cmnd_matches == TRUE) { - /* - * User was granted access to cmnd on host as user. - */ -#ifdef HAVE_SELINUX - /* Set role and type if not specified on command line. */ - if (user_role == NULL) { - if (match[top-1].role != NULL) - user_role = match[top-1].role; - else - user_role = def_role; - } - if (user_type == NULL) { - if (match[top-1].type != NULL) - user_type = match[top-1].type; - else - user_type = def_type; - } -#endif - set_perms(PERM_ROOT); - return(VALIDATE_OK | - (no_passwd == TRUE ? FLAG_NOPASS : 0) | - (no_execve == TRUE ? FLAG_NOEXEC : 0) | - (setenv_ok >= TRUE ? FLAG_SETENV : 0)); - } else if ((runas_matches == TRUE && cmnd_matches == FALSE) || - (runas_matches == FALSE && cmnd_matches == TRUE)) { - /* - * User was explicitly denied access to cmnd on host. - */ - set_perms(PERM_ROOT); - return(VALIDATE_NOT_OK | - (no_passwd == TRUE ? FLAG_NOPASS : 0) | - (no_execve == TRUE ? FLAG_NOEXEC : 0) | - (setenv_ok >= TRUE ? FLAG_SETENV : 0)); + nopass = (pwcheck == all) ? TRUE : FALSE; + + if (list_pw == NULL) + SET(validated, FLAG_NO_CHECK); + CLR(validated, FLAG_NO_USER); + CLR(validated, FLAG_NO_HOST); + match = DENY; + tq_foreach_fwd(&userspecs, us) { + if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) + continue; + tq_foreach_fwd(&us->privileges, priv) { + if (hostlist_matches(&priv->hostlist) != ALLOW) + continue; + tq_foreach_fwd(&priv->cmndlist, cs) { + /* Only check the command when listing another user. */ + if (user_uid == 0 || list_pw == NULL || + user_uid == list_pw->pw_uid || + cmnd_matches(cs->cmnd) == ALLOW) + match = ALLOW; + if ((pwcheck == any && cs->tags.nopasswd == TRUE) || + (pwcheck == all && cs->tags.nopasswd != TRUE)) + nopass = cs->tags.nopasswd; } } - top--; } + if (match == ALLOW || user_uid == 0) { + /* User has an entry for this host. */ + SET(validated, VALIDATE_OK); + } else if (match == DENY) + SET(validated, VALIDATE_NOT_OK); + if (pwcheck == always && def_authenticate) + SET(validated, FLAG_CHECK_USER); + else if (pwcheck == never || nopass == TRUE) + def_authenticate = FALSE; + return(validated); } - set_perms(PERM_ROOT); - /* - * The user was neither explicitly granted nor denied access. - */ - if (nopass == -1) - nopass = 0; - return(error | nopass); -} - -/* - * If path doesn't end in /, return TRUE iff cmnd & path name the same inode; - * otherwise, return TRUE if user_cmnd names one of the inodes in path. - */ -int -command_matches(sudoers_cmnd, sudoers_args) - char *sudoers_cmnd; - char *sudoers_args; -{ - struct stat sudoers_stat; - struct dirent *dent; - char **ap, *base, buf[PATH_MAX]; - glob_t gl; - DIR *dirp; - - /* Check for pseudo-commands */ - if (strchr(user_cmnd, '/') == NULL) { - /* - * Return true if both sudoers_cmnd and user_cmnd are "sudoedit" 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 (strcmp(sudoers_cmnd, "sudoedit") != 0 || - strcmp(user_cmnd, "sudoedit") != 0) - 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); - } else - return(FALSE); - } + /* Need to be runas user while stat'ing things. */ + set_perms(PERM_RUNAS); - /* - * If sudoers_cmnd has meta characters in it, use fnmatch(3) - * to do the matching. - */ - if (has_meta(sudoers_cmnd)) { - /* - * 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. - * - * Could optimize patterns ending in "/*" to "/user_base" - */ -#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; *ap != NULL; ap++) { - /* only stat if basenames are the same */ - if ((base = strrchr(*ap, '/')) != NULL) - base++; + match = UNSPEC; + tq_foreach_rev(&userspecs, us) { + if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) + continue; + CLR(validated, FLAG_NO_USER); + tq_foreach_rev(&us->privileges, priv) { + host_match = hostlist_matches(&priv->hostlist); + if (host_match == ALLOW) + CLR(validated, FLAG_NO_HOST); else - base = *ap; - if (strcmp(user_base, base) != 0 || - stat(*ap, &sudoers_stat) == -1) continue; - if (user_stat->st_dev == sudoers_stat.st_dev && - user_stat->st_ino == sudoers_stat.st_ino) { - efree(safe_cmnd); - safe_cmnd = estrdup(*ap); - break; + tq_foreach_rev(&priv->cmndlist, cs) { + runas_match = runaslist_matches(&cs->runasuserlist, + &cs->runasgrouplist); + if (runas_match == ALLOW) { + cmnd_match = cmnd_matches(cs->cmnd); + if (cmnd_match != UNSPEC) { + match = cmnd_match; + tags = &cs->tags; +#ifdef HAVE_SELINUX + /* Set role and type if not specified on command line. */ + if (user_role == NULL) + user_role = cs->role ? estrdup(cs->role) : def_role; + if (user_type == NULL) + user_type = cs->type ? estrdup(cs->type) : def_type; +#endif /* HAVE_SELINUX */ + goto matched2; + } + } } } - globfree(&gl); - if (*ap == 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); - } else - return(FALSE); - } else { - size_t dlen = strlen(sudoers_cmnd); - - /* - * No meta characters - * Check to make sure this is not a directory spec (doesn't end in '/') - */ - if (sudoers_cmnd[dlen - 1] != '/') { - /* 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->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); - } else - return(FALSE); + } + matched2: + if (match == ALLOW) { + SET(validated, VALIDATE_OK); + CLR(validated, VALIDATE_NOT_OK); + if (tags != NULL) { + if (tags->nopasswd != UNSPEC) + def_authenticate = !tags->nopasswd; + if (tags->noexec != UNSPEC) + def_noexec = tags->noexec; + if (tags->setenv != UNSPEC) + def_setenv = tags->setenv; } + } else if (match == DENY) { + SET(validated, VALIDATE_NOT_OK); + CLR(validated, VALIDATE_OK); + } + set_perms(PERM_ROOT); + return(validated); +} - /* - * Grot through sudoers_cmnd's directory entries, looking for user_base. - */ - dirp = opendir(sudoers_cmnd); - if (dirp == NULL) - return(FALSE); - - if (strlcpy(buf, sudoers_cmnd, sizeof(buf)) >= sizeof(buf)) - return(FALSE); - while ((dent = readdir(dirp)) != NULL) { - /* ignore paths > PATH_MAX (XXX - log) */ - buf[dlen] = '\0'; - if (strlcat(buf, dent->d_name, sizeof(buf)) >= sizeof(buf)) - continue; +#define TAG_CHANGED(t) \ + (cs->tags.t != UNSPEC && cs->tags.t != IMPLIED && cs->tags.t != tags->t) - /* only stat if basenames are the same */ - if (strcmp(user_base, dent->d_name) != 0 || - stat(buf, &sudoers_stat) == -1) - continue; - if (user_stat->st_dev == sudoers_stat.st_dev && - user_stat->st_ino == sudoers_stat.st_ino) { - efree(safe_cmnd); - safe_cmnd = estrdup(buf); - break; - } - } +static void +sudo_file_append_cmnd(cs, tags, lbuf) + struct cmndspec *cs; + struct cmndtag *tags; + struct lbuf *lbuf; +{ + struct member *m; - closedir(dirp); - return(dent != NULL); +#ifdef HAVE_SELINUX + if (cs->role) + lbuf_append(lbuf, "ROLE=", cs->role, " ", NULL); + if (cs->type) + lbuf_append(lbuf, "TYPE=", cs->type, " ", NULL); +#endif /* HAVE_SELINUX */ + if (TAG_CHANGED(setenv)) { + lbuf_append(lbuf, cs->tags.setenv ? "SETENV: " : + "NOSETENV: ", NULL); + tags->setenv = cs->tags.setenv; + } + if (TAG_CHANGED(noexec)) { + lbuf_append(lbuf, cs->tags.noexec ? "NOEXEC: " : + "EXEC: ", NULL); + tags->noexec = cs->tags.noexec; + } + if (TAG_CHANGED(nopasswd)) { + lbuf_append(lbuf, cs->tags.nopasswd ? "NOPASSWD: " : + "PASSWD: ", NULL); + tags->nopasswd = cs->tags.nopasswd; } + m = cs->cmnd; + print_member(lbuf, m->name, m->type, m->negated, + CMNDALIAS); } static int -addr_matches_if(n) - char *n; +sudo_file_display_priv_short(pw, us, lbuf) + struct passwd *pw; + struct userspec *us; + struct lbuf *lbuf; { - int i; - struct in_addr addr; - struct interface *ifp; -#ifdef HAVE_IN6_ADDR - struct in6_addr addr6; - int j; -#endif - int family; - -#ifdef HAVE_IN6_ADDR - if (inet_pton(AF_INET6, n, &addr6) > 0) { - family = AF_INET6; - } else -#endif - { - family = AF_INET; - addr.s_addr = inet_addr(n); - } - - for (i = 0; i < num_interfaces; i++) { - ifp = &interfaces[i]; - if (ifp->family != family) - continue; - switch(family) { - case AF_INET: - if (ifp->addr.ip4.s_addr == addr.s_addr || - (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr) - == addr.s_addr) - return(TRUE); - break; -#ifdef HAVE_IN6_ADDR - case AF_INET6: - if (memcmp(ifp->addr.ip6.s6_addr, addr6.s6_addr, - sizeof(addr6.s6_addr)) == 0) - return(TRUE); - for (j = 0; j < sizeof(addr6.s6_addr); j++) { - if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr6.s6_addr[j]) - break; + struct cmndspec *cs; + struct member *m; + struct privilege *priv; + struct cmndtag tags; + int nfound = 0; + + tq_foreach_fwd(&us->privileges, priv) { + tags.noexec = UNSPEC; + tags.setenv = UNSPEC; + tags.nopasswd = UNSPEC; + lbuf_append(lbuf, " ", NULL); + tq_foreach_fwd(&priv->cmndlist, cs) { + if (cs != tq_first(&priv->cmndlist)) + lbuf_append(lbuf, ", ", NULL); + lbuf_append(lbuf, "(", NULL); + if (!tq_empty(&cs->runasuserlist)) { + tq_foreach_fwd(&cs->runasuserlist, m) { + if (m != tq_first(&cs->runasuserlist)) + lbuf_append(lbuf, ", ", NULL); + print_member(lbuf, m->name, m->type, m->negated, + RUNASALIAS); } - if (j == sizeof(addr6.s6_addr)) - return(TRUE); -#endif /* HAVE_IN6_ADDR */ + } else { + lbuf_append(lbuf, def_runas_default, NULL); + } + if (!tq_empty(&cs->runasgrouplist)) { + lbuf_append(lbuf, " : ", NULL); + tq_foreach_fwd(&cs->runasgrouplist, m) { + if (m != tq_first(&cs->runasgrouplist)) + lbuf_append(lbuf, ", ", NULL); + print_member(lbuf, m->name, m->type, m->negated, + RUNASALIAS); + } + } + lbuf_append(lbuf, ") ", NULL); + sudo_file_append_cmnd(cs, &tags, lbuf); + nfound++; } + lbuf_print(lbuf); /* forces a newline */ } - - return(FALSE); + return(nfound); } static int -addr_matches_if_netmask(n, m) - char *n; - char *m; +sudo_file_display_priv_long(pw, us, lbuf) + struct passwd *pw; + struct userspec *us; + struct lbuf *lbuf; { - int i; - struct in_addr addr, mask; - struct interface *ifp; -#ifdef HAVE_IN6_ADDR - struct in6_addr addr6, mask6; - int j; -#endif - int family; - -#ifdef HAVE_IN6_ADDR - if (inet_pton(AF_INET6, n, &addr6) > 0) - family = AF_INET6; - else -#endif - { - family = AF_INET; - addr.s_addr = inet_addr(n); - } - - if (family == AF_INET) { - if (strchr(m, '.')) - mask.s_addr = inet_addr(m); - else { - i = 32 - atoi(m); - mask.s_addr = 0xffffffff; - mask.s_addr >>= i; - mask.s_addr <<= i; - mask.s_addr = htonl(mask.s_addr); - } - } -#ifdef HAVE_IN6_ADDR - else { - if (inet_pton(AF_INET6, m, &mask6) <= 0) { - j = atoi(m); - for (i = 0; i < 16; i++) { - if (j < i * 8) - mask6.s6_addr[i] = 0; - else if (i * 8 + 8 <= j) - mask6.s6_addr[i] = 0xff; - else - mask6.s6_addr[i] = 0xff00 >> (j - i * 8); + struct cmndspec *cs; + struct member *m; + struct privilege *priv; + struct cmndtag tags; + int nfound = 0; + + tq_foreach_fwd(&us->privileges, priv) { + tags.noexec = UNSPEC; + tags.setenv = UNSPEC; + tags.nopasswd = UNSPEC; + lbuf_print(lbuf); /* force a newline */ + lbuf_append(lbuf, "Sudoers entry:", NULL); + lbuf_print(lbuf); + tq_foreach_fwd(&priv->cmndlist, cs) { + lbuf_append(lbuf, " RunAsUsers: ", NULL); + if (!tq_empty(&cs->runasuserlist)) { + tq_foreach_fwd(&cs->runasuserlist, m) { + if (m != tq_first(&cs->runasuserlist)) + lbuf_append(lbuf, ", ", NULL); + print_member(lbuf, m->name, m->type, m->negated, + RUNASALIAS); + } + } else { + lbuf_append(lbuf, def_runas_default, NULL); } - } - } -#endif /* HAVE_IN6_ADDR */ - - for (i = 0; i < num_interfaces; i++) { - ifp = &interfaces[i]; - if (ifp->family != family) - continue; - switch(family) { - case AF_INET: - if ((ifp->addr.ip4.s_addr & mask.s_addr) == addr.s_addr) - return(TRUE); -#ifdef HAVE_IN6_ADDR - case AF_INET6: - for (j = 0; j < sizeof(addr6.s6_addr); j++) { - if ((ifp->addr.ip6.s6_addr[j] & mask6.s6_addr[j]) != addr6.s6_addr[j]) - break; + lbuf_print(lbuf); + if (!tq_empty(&cs->runasgrouplist)) { + lbuf_append(lbuf, " RunAsGroups: ", NULL); + tq_foreach_fwd(&cs->runasgrouplist, m) { + if (m != tq_first(&cs->runasgrouplist)) + lbuf_append(lbuf, ", ", NULL); + print_member(lbuf, m->name, m->type, m->negated, + RUNASALIAS); } - if (j == sizeof(addr6.s6_addr)) - return(TRUE); -#endif /* HAVE_IN6_ADDR */ + lbuf_print(lbuf); + } + lbuf_append(lbuf, " Commands: ", NULL); + lbuf_print(lbuf); + lbuf_append(lbuf, "\t", NULL); + sudo_file_append_cmnd(cs, &tags, lbuf); + lbuf_print(lbuf); + nfound++; } } - - return(FALSE); + return(nfound); } -/* - * Returns TRUE if "n" is one of our ip addresses or if - * "n" is a network that we are on, else returns FALSE. - */ int -addr_matches(n) - char *n; +sudo_file_display_privs(nss, pw, lbuf) + struct sudo_nss *nss; + struct passwd *pw; + struct lbuf *lbuf; { - char *m; - int retval; - - /* If there's an explicit netmask, use it. */ - if ((m = strchr(n, '/'))) { - *m++ = '\0'; - retval = addr_matches_if_netmask(n, m); - *(m - 1) = '/'; - } else - retval = addr_matches_if(n); - - return(retval); -} + struct userspec *us; + int nfound = 0; -/* - * Returns 0 if the hostname matches the pattern and non-zero otherwise. - */ -int -hostname_matches(shost, lhost, pattern) - char *shost; - char *lhost; - char *pattern; -{ - if (has_meta(pattern)) { - if (strchr(pattern, '.')) - return(fnmatch(pattern, lhost, FNM_CASEFOLD)); - else - return(fnmatch(pattern, shost, FNM_CASEFOLD)); - } else { - if (strchr(pattern, '.')) - return(strcasecmp(lhost, pattern)); + if (nss->handle == NULL) + return(-1); + + tq_foreach_fwd(&userspecs, us) { + /* XXX - why only check the first privilege here? */ + if (userlist_matches(pw, &us->users) != ALLOW || + hostlist_matches(&us->privileges.first->hostlist) != ALLOW) + continue; + + if (long_list) + nfound += sudo_file_display_priv_long(pw, us, lbuf); else - return(strcasecmp(shost, pattern)); + nfound += sudo_file_display_priv_short(pw, us, lbuf); } + return(nfound); } /* - * Returns TRUE if the user/uid from sudoers matches the specified user/uid, - * else returns FALSE. + * Display matching Defaults entries for the given user on this host. */ int -userpw_matches(sudoers_user, user, pw) - char *sudoers_user; - char *user; +sudo_file_display_defaults(nss, pw, lbuf) + struct sudo_nss *nss; struct passwd *pw; + struct lbuf *lbuf; { - if (pw != NULL && *sudoers_user == '#') { - uid_t uid = atoi(sudoers_user + 1); - if (uid == pw->pw_uid) - return(1); + struct defaults *d; + char *prefix = NULL; + int nfound = 0; + + if (nss->handle == NULL) + return(-1); + + if (lbuf->len == 0) + prefix = " "; + else + prefix = ", "; + + tq_foreach_fwd(&defaults, d) { + switch (d->type) { + case DEFAULTS_HOST: + if (hostlist_matches(&d->binding) != ALLOW) + continue; + break; + case DEFAULTS_USER: + if (userlist_matches(pw, &d->binding) != ALLOW) + continue; + break; + case DEFAULTS_RUNAS: + case DEFAULTS_CMND: + continue; + } + lbuf_append(lbuf, prefix, NULL); + if (d->val != NULL) { + lbuf_append(lbuf, d->var, d->op == '+' ? "+=" : + d->op == '-' ? "-=" : "=", NULL); + if (strpbrk(d->val, " \t") != NULL) { + lbuf_append(lbuf, "\"", NULL); + lbuf_append_quoted(lbuf, "\"", d->val, NULL); + lbuf_append(lbuf, "\"", NULL); + } else + lbuf_append_quoted(lbuf, SUDOERS_QUOTED, d->val, NULL); + } else + lbuf_append(lbuf, d->op == FALSE ? "!" : "", d->var, NULL); + prefix = ", "; + nfound++; } - return(strcmp(sudoers_user, user) == 0); + + return(nfound); } /* - * Returns TRUE if the given user belongs to the named group, - * else returns FALSE. - * XXX - reduce the number of passwd/group lookups + * Display Defaults entries that are per-runas or per-command */ int -usergr_matches(group, user, pw) - char *group; - char *user; +sudo_file_display_bound_defaults(nss, pw, lbuf) + struct sudo_nss *nss; struct passwd *pw; + struct lbuf *lbuf; { - struct group *grp; - gid_t pw_gid; - char **cur; - int i; + int nfound = 0; - /* make sure we have a valid usergroup, sudo style */ - if (*group++ != '%') - return(FALSE); + /* XXX - should only print ones that match what the user can do. */ + nfound += display_bound_defaults(DEFAULTS_RUNAS, lbuf); + nfound += display_bound_defaults(DEFAULTS_CMND, lbuf); - /* look up user's primary gid in the passwd file */ - if (pw == NULL && (pw = getpwnam(user)) == NULL) - return(FALSE); - pw_gid = pw->pw_gid; - - if ((grp = getgrnam(group)) == NULL) - return(FALSE); - - /* check against user's primary (passwd file) gid */ - if (grp->gr_gid == pw_gid) - return(TRUE); + return(nfound); +} - /* - * If the user has a supplementary group vector, check it first. - */ - for (i = 0; i < user_ngroups; i++) { - if (grp->gr_gid == user_groups[i]) - return(TRUE); +/* + * Display Defaults entries of the given type. + */ +static int +display_bound_defaults(dtype, lbuf) + int dtype; + struct lbuf *lbuf; +{ + struct defaults *d; + struct member *m, *binding = NULL; + char *dname, *dsep; + int atype, nfound = 0; + + switch (dtype) { + case DEFAULTS_HOST: + atype = HOSTALIAS; + dname = "host"; + dsep = "@"; + break; + case DEFAULTS_USER: + atype = USERALIAS; + dname = "user"; + dsep = ":"; + break; + case DEFAULTS_RUNAS: + atype = RUNASALIAS; + dname = "runas"; + dsep = ">"; + break; + case DEFAULTS_CMND: + atype = CMNDALIAS; + dname = "cmnd"; + dsep = "!"; + break; + default: + return(-1); } - if (grp->gr_mem != NULL) { - for (cur = grp->gr_mem; *cur; cur++) { - if (strcmp(*cur, user) == 0) - return(TRUE); - } + /* printf("Per-%s Defaults entries:\n", dname); */ + tq_foreach_fwd(&defaults, d) { + if (d->type != dtype) + continue; + + nfound++; + if (binding != tq_first(&d->binding)) { + binding = tq_first(&d->binding); + lbuf_append(lbuf, " Defaults", dsep, NULL); + for (m = binding; m != NULL; m = m->next) { + if (m != binding) + lbuf_append(lbuf, ",", NULL); + print_member(lbuf, m->name, m->type, m->negated, atype); + lbuf_append(lbuf, " ", NULL); + } + } else + lbuf_append(lbuf, ", ", NULL); + if (d->val != NULL) { + lbuf_append(lbuf, d->var, d->op == '+' ? "+=" : + d->op == '-' ? "-=" : "=", d->val, NULL); + } else + lbuf_append(lbuf, d->op == FALSE ? "!" : "", d->var, NULL); } - return(FALSE); + return(nfound); } -/* - * Returns TRUE if "host" and "user" belong to the netgroup "netgr", - * else return FALSE. Either of "host", "shost" or "user" may be NULL - * in which case that argument is not checked... - */ int -netgr_matches(netgr, host, shost, user) - char *netgr; - char *host; - char *shost; - char *user; +sudo_file_display_cmnd(nss, pw) + struct sudo_nss *nss; + struct passwd *pw; { - static char *domain; -#ifdef HAVE_GETDOMAINNAME - static int initialized; -#endif - - /* make sure we have a valid netgroup, sudo style */ - if (*netgr++ != '+') - return(FALSE); - -#ifdef HAVE_GETDOMAINNAME - /* get the domain name (if any) */ - if (!initialized) { - domain = (char *) emalloc(MAXHOSTNAMELEN); - if (getdomainname(domain, MAXHOSTNAMELEN) == -1 || *domain == '\0') { - efree(domain); - domain = NULL; + struct cmndspec *cs; + struct member *match; + struct privilege *priv; + struct userspec *us; + int rval = 1; + int host_match, runas_match, cmnd_match; + + if (nss->handle == NULL) + return(rval); + + match = NULL; + tq_foreach_rev(&userspecs, us) { + if (userlist_matches(pw, &us->users) != ALLOW) + continue; + + tq_foreach_rev(&us->privileges, priv) { + host_match = hostlist_matches(&priv->hostlist); + if (host_match != ALLOW) + continue; + tq_foreach_rev(&priv->cmndlist, cs) { + runas_match = runaslist_matches(&cs->runasuserlist, + &cs->runasgrouplist); + if (runas_match == ALLOW) { + cmnd_match = cmnd_matches(cs->cmnd); + if (cmnd_match != UNSPEC) { + match = host_match && runas_match ? + cs->cmnd : NULL; + goto matched; + } + } + } } - initialized = 1; } -#endif /* HAVE_GETDOMAINNAME */ - -#ifdef HAVE_INNETGR - if (innetgr(netgr, host, user, domain)) - return(TRUE); - else if (host != shost && innetgr(netgr, shost, user, domain)) - return(TRUE); -#endif /* HAVE_INNETGR */ - - return(FALSE); + matched: + if (match != NULL && !match->negated) { + printf("%s%s%s\n", safe_cmnd, user_args ? " " : "", + user_args ? user_args : ""); + rval = 0; + } + return(rval); } /* - * Returns TRUE if "s" has shell meta characters in it, - * else returns FALSE. + * Print the contents of a struct member to stdout */ -static int -has_meta(s) - char *s; +static void +_print_member(lbuf, name, type, negated, alias_type) + struct lbuf *lbuf; + char *name; + int type, negated, alias_type; { - char *t; - - for (t = s; *t; t++) { - if (*t == '\\' || *t == '?' || *t == '*' || *t == '[' || *t == ']') - return(TRUE); + struct alias *a; + struct member *m; + struct sudo_command *c; + + switch (type) { + case ALL: + lbuf_append(lbuf, negated ? "!ALL" : "ALL", NULL); + break; + case COMMAND: + c = (struct sudo_command *) name; + if (negated) + lbuf_append(lbuf, "!", NULL); + lbuf_append_quoted(lbuf, SUDOERS_QUOTED, c->cmnd, NULL); + if (c->args) { + lbuf_append(lbuf, " ", NULL); + lbuf_append_quoted(lbuf, SUDOERS_QUOTED, c->args, NULL); + } + break; + case ALIAS: + if ((a = find_alias(name, alias_type)) != NULL) { + tq_foreach_fwd(&a->members, m) { + if (m != tq_first(&a->members)) + lbuf_append(lbuf, ", ", NULL); + _print_member(lbuf, m->name, m->type, + negated ? !m->negated : m->negated, alias_type); + } + break; + } + /* FALLTHROUGH */ + default: + lbuf_append(lbuf, negated ? "!" : "", name, NULL); + break; } - return(FALSE); +} + +static void +print_member(lbuf, name, type, negated, alias_type) + struct lbuf *lbuf; + char *name; + int type, negated, alias_type; +{ + alias_seqno++; + _print_member(lbuf, name, type, negated, alias_type); } diff --git a/parse.h b/parse.h index a9bbc8e..1638858 100644 --- a/parse.h +++ b/parse.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2000, 2004, 2007 + * Copyright (c) 1996, 1998-2000, 2004, 2007-2008 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -14,40 +14,40 @@ * 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.14.2.2 2008/02/09 14:44:48 millert Exp $ + * $Sudo: parse.h,v 1.44 2008/11/09 14:13:12 millert Exp $ */ #ifndef _SUDO_PARSE_H #define _SUDO_PARSE_H -/* - * Data structure used in parsing sudoers; - * top of stack values are the ones that - * apply when parsing is done & can be - * accessed by *_matches macros - */ -#define STACKINCREMENT (32) -struct matchstack { - int user; - int cmnd; - int host; - int runas; - int nopass; - int noexec; - int setenv; - char *role; - char *type; -}; +#undef UNSPEC +#define UNSPEC -1 +#undef DENY +#define DENY 0 +#undef ALLOW +#define ALLOW 1 +#undef IMPLIED +#define IMPLIED 2 /* - * Data structure describing a command in the - * sudoers file. + * A command with args. XXX - merge into struct member. */ struct sudo_command { char *cmnd; char *args; }; +/* + * Tags associated with a command. + * Possible valus: TRUE, FALSE, UNSPEC. + */ +struct cmndtag { + __signed char nopasswd; + __signed char noexec; + __signed char setenv; + __signed char extra; +}; + /* * SELinux-specific container struct. * Currently just contains a role and type. @@ -57,67 +57,133 @@ struct selinux_info { char *type; }; -#define user_matches (match[top-1].user) -#define cmnd_matches (match[top-1].cmnd) -#define host_matches (match[top-1].host) -#define runas_matches (match[top-1].runas) -#define no_passwd (match[top-1].nopass) -#define no_execve (match[top-1].noexec) -#define setenv_ok (match[top-1].setenv) +/* + * The parses sudoers file is stored as a collection of linked lists, + * modelled after the yacc grammar. + * + * Other than the alias struct, which is stored in a red-black tree, + * the data structure used is basically a doubly-linked tail queue without + * a separate head struct--the first entry acts as the head where the prev + * pointer does double duty as the tail pointer. This makes it possible + * to trivally append sub-lists. In addition, the prev pointer is always + * valid (even if it points to itself). Unlike a circle queue, the next + * pointer of the last entry is NULL and does not point back to the head. + * + * Note that each list struct must contain a "prev" and "next" pointer as + * the first two members of the struct (in that order). + */ + +/* + * Tail queue list head structure. + */ +TQ_DECLARE(defaults) +TQ_DECLARE(userspec) +TQ_DECLARE(member) +TQ_DECLARE(privilege) +TQ_DECLARE(cmndspec) /* - * Structure containing command matches if "sudo -l" is used. + * Structure describing a user specification and list thereof. */ -struct command_match { - char *runas; - size_t runas_len; - size_t runas_size; - char *cmnd; - size_t cmnd_len; - size_t cmnd_size; - char *role; - size_t role_len; - size_t role_size; - char *type; - size_t type_len; - size_t type_size; - int nopasswd; - int noexecve; - int setenv; +struct userspec { + struct userspec *prev, *next; + struct member_list users; /* list of users */ + struct privilege_list privileges; /* list of privileges */ }; /* - * Structure describing an alias match in parser. + * Structure describing a privilege specification. */ -typedef struct { - int type; - char *name; - int val; -} aliasinfo; +struct privilege { + struct privilege *prev, *next; + struct member_list hostlist; /* list of hosts */ + struct cmndspec_list cmndlist; /* list of Cmnd_Specs */ +}; /* - * Structure containing Cmnd_Alias's if "sudo -l" is used. + * Structure describing a linked list of Cmnd_Specs. */ -struct generic_alias { - int type; - char *alias; - char *entries; - size_t entries_size; - size_t entries_len; +struct cmndspec { + struct cmndspec *prev, *next; + struct member_list runasuserlist; /* list of runas users */ + struct member_list runasgrouplist; /* list of runas groups */ + struct member *cmnd; /* command to allow/deny */ + struct cmndtag tags; /* tag specificaion */ +#ifdef HAVE_SELINUX + char *role, *type; /* SELinux role and type */ +#endif }; -/* The matching stack and number of entries on it. */ -extern struct matchstack *match; -extern int top; +/* + * Generic structure to hold users, hosts, commands. + */ +struct member { + struct member *prev, *next; + char *name; /* member name */ + short type; /* type (see gram.h) */ + short negated; /* negated via '!'? */ +}; + +struct runascontainer { + struct member *runasusers; + struct member *runasgroups; +}; + +/* + * Generic structure to hold {User,Host,Runas,Cmnd}_Alias + * Aliases are stored in a red-black tree, sorted by name and type. + */ +struct alias { + char *name; /* alias name */ + unsigned short type; /* {USER,HOST,RUNAS,CMND}ALIAS */ + unsigned short seqno; /* sequence number */ + struct member_list members; /* list of alias members */ +}; + +/* + * Structure describing a Defaults entry and a list thereof. + */ +struct defaults { + struct defaults *prev, *next; + char *var; /* variable name */ + char *val; /* variable value */ + struct member_list binding; /* user/host/runas binding */ + int type; /* DEFAULTS{,_USER,_RUNAS,_HOST} */ + int op; /* TRUE, FALSE, '+', '-' */ +}; + +/* + * Parsed sudoers info. + */ +extern struct userspec_list userspecs; +extern struct defaults_list defaults; + +/* + * Alias sequence number to avoid loops. + */ +extern unsigned int alias_seqno; /* * Prototypes */ +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 *)); +int hostlist_matches __P((struct member_list *)); int hostname_matches __P((char *, char *, char *)); int netgr_matches __P((char *, char *, char *, char *)); -int userpw_matches __P((char *, char *, struct passwd *)); +int no_aliases __P((void)); +int runaslist_matches __P((struct member_list *, struct member_list *)); +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)); +void alias_apply __P((int (*)(void *, void *), void *)); +void init_aliases __P((void)); +void init_parser __P((char *, int)); #endif /* _SUDO_PARSE_H */ diff --git a/parse.lex b/parse.lex deleted file mode 100644 index 41eba10..0000000 --- a/parse.lex +++ /dev/null @@ -1,580 +0,0 @@ -%{ -/* - * Copyright (c) 1996, 1998-2004, 2007 - * 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. - * 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. - * - * 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. - */ - -#include - -#include -#include -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif /* STDC_HEADERS */ -#ifdef HAVE_STRING_H -# include -#else -# ifdef HAVE_STRINGS_H -# include -# endif -#endif /* HAVE_STRING_H */ -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ -#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) -# include -#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ -#include -#include "sudo.h" -#include "parse.h" -#include - -#ifndef lint -__unused static const char rcsid[] = "$Sudo: parse.lex,v 1.132.2.10 2008/06/26 11:53:50 millert Exp $"; -#endif /* lint */ - -#undef yywrap /* guard against a yywrap macro */ - -extern YYSTYPE yylval; -extern int clearaliases; -int sudolineno = 1; -static int sawspace = 0; -static int arg_len = 0; -static int arg_size = 0; - -static int ipv6_valid __P((const char *s)); -static void _fill __P((char *, int, int)); -static void append __P((char *, int)); -static void fill_cmnd __P((char *, int)); -static void fill_args __P((char *, int, int)); -extern void reset_aliases __P((void)); -extern void yyerror __P((char *)); - -#define fill(a, b) _fill(a, b, 0) - -/* realloc() to size + COMMANDARGINC to make room for command args */ -#define COMMANDARGINC 64 - -#ifdef TRACELEXER -#define LEXTRACE(msg) fputs(msg, stderr) -#else -#define LEXTRACE(msg) -#endif -%} - -HEX16 [0-9A-Fa-f]{1,4} -OCTET (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]) -IPV4ADDR {OCTET}(\.{OCTET}){3} -IPV6ADDR ({HEX16}?:){2,7}{HEX16}?|({HEX16}?:){2,6}:{IPV4ADDR} - -HOSTNAME [[:alnum:]_-]+ -WORD ([^#>@!=:,\(\) \t\n\\]|\\[^\n])+ -ENVAR ([^#!=, \t\n\\\"]|\\[^\n])([^#=, \t\n\\]|\\[^\n])* -DEFVAR [a-z_]+ - -/* XXX - convert GOTRUNAS to exclusive state (GOTDEFS cannot be) */ -%s GOTRUNAS -%s GOTDEFS -%x GOTCMND -%x STARTDEFS -%x INDEFS -%x INSTR - -%% -[[:blank:]]+ BEGIN STARTDEFS; - -{DEFVAR} { - BEGIN INDEFS; - LEXTRACE("DEFVAR "); - fill(yytext, yyleng); - return(DEFVAR); - } - -{ - , { - BEGIN STARTDEFS; - LEXTRACE(", "); - return(','); - } /* return ',' */ - - = { - LEXTRACE("= "); - return('='); - } /* return '=' */ - - \+= { - LEXTRACE("+= "); - return('+'); - } /* return '+' */ - - -= { - LEXTRACE("-= "); - return('-'); - } /* return '-' */ - - \" { - LEXTRACE("BEGINSTR "); - yylval.string = NULL; - BEGIN INSTR; - } - - {ENVAR} { - LEXTRACE("WORD(2) "); - fill(yytext, yyleng); - return(WORD); - } -} - -{ - \\[[:blank:]]*\n[[:blank:]]* { - /* Line continuation char followed by newline. */ - ++sudolineno; - LEXTRACE("\n"); - } - - \" { - LEXTRACE("ENDSTR "); - BEGIN INDEFS; - return(WORD); - } - - \\ { - LEXTRACE("BACKSLASH "); - append(yytext, yyleng); - } - - ([^\"\n\\]|\\\")+ { - LEXTRACE("STRBODY "); - append(yytext, yyleng); - } -} - -{ - \\[\*\?\[\]\!] { - /* quoted fnmatch glob char, pass verbatim */ - LEXTRACE("QUOTEDCHAR "); - fill_args(yytext, 2, sawspace); - sawspace = FALSE; - } - - \\[:\\,= \t#] { - /* quoted sudoers special char, strip backslash */ - LEXTRACE("QUOTEDCHAR "); - fill_args(yytext + 1, 1, sawspace); - sawspace = FALSE; - } - - [#:\,=\n] { - BEGIN INITIAL; - unput(*yytext); - return(COMMAND); - } /* end of command line args */ - - [^\\:, \t\n]+ { - LEXTRACE("ARG "); - fill_args(yytext, yyleng, sawspace); - sawspace = FALSE; - } /* a command line arg */ -} - -^Defaults[:@>]? { - BEGIN GOTDEFS; - switch (yytext[8]) { - case ':': - LEXTRACE("DEFAULTS_USER "); - return(DEFAULTS_USER); - case '>': - LEXTRACE("DEFAULTS_RUNAS "); - return(DEFAULTS_RUNAS); - case '@': - LEXTRACE("DEFAULTS_HOST "); - return(DEFAULTS_HOST); - default: - LEXTRACE("DEFAULTS "); - return(DEFAULTS); - } - } - -^(Host|Cmnd|User|Runas)_Alias { - fill(yytext, yyleng); - switch (*yytext) { - case 'H': - LEXTRACE("HOSTALIAS "); - return(HOSTALIAS); - case 'C': - LEXTRACE("CMNDALIAS "); - return(CMNDALIAS); - case 'U': - LEXTRACE("USERALIAS "); - return(USERALIAS); - case 'R': - LEXTRACE("RUNASALIAS "); - BEGIN GOTRUNAS; - return(RUNASALIAS); - } - } - -NOPASSWD[[:blank:]]*: { - /* cmnd does not require passwd for this user */ - LEXTRACE("NOPASSWD "); - return(NOPASSWD); - } - -PASSWD[[:blank:]]*: { - /* cmnd requires passwd for this user */ - LEXTRACE("PASSWD "); - return(PASSWD); - } - -NOEXEC[[:blank:]]*: { - LEXTRACE("NOEXEC "); - return(NOEXEC); - } - -EXEC[[:blank:]]*: { - LEXTRACE("EXEC "); - return(EXEC); - } - -SETENV[[:blank:]]*: { - LEXTRACE("SETENV "); - return(SETENV); - } - -NOSETENV[[:blank:]]*: { - LEXTRACE("NOSETENV "); - return(NOSETENV); - } - -\+{WORD} { - /* netgroup */ - fill(yytext, yyleng); - LEXTRACE("NETGROUP "); - return(NETGROUP); - } - -\%{WORD} { - /* UN*X group */ - fill(yytext, yyleng); - LEXTRACE("GROUP "); - return(USERGROUP); - } - -{IPV4ADDR}(\/{IPV4ADDR})? { - fill(yytext, yyleng); - LEXTRACE("NTWKADDR "); - return(NTWKADDR); - } - -{IPV4ADDR}\/([12][0-9]*|3[0-2]*) { - fill(yytext, yyleng); - LEXTRACE("NTWKADDR "); - return(NTWKADDR); - } - -{IPV6ADDR}(\/{IPV6ADDR})? { - if (!ipv6_valid(yytext)) { - LEXTRACE("ERROR "); - return(ERROR); - } - fill(yytext, yyleng); - LEXTRACE("NTWKADDR "); - return(NTWKADDR); - } - -{IPV6ADDR}\/([0-9]|[1-9][0-9]|1[01][0-9]|12[0-8]) { - if (!ipv6_valid(yytext)) { - LEXTRACE("ERROR "); - return(ERROR); - } - fill(yytext, yyleng); - LEXTRACE("NTWKADDR "); - return(NTWKADDR); - } - -\( { - BEGIN GOTRUNAS; - LEXTRACE("RUNAS "); - return (RUNAS); - } - -[[:upper:]][[:upper:][:digit:]_]* { - if (strcmp(yytext, "ALL") == 0) { - LEXTRACE("ALL "); - return(ALL); - } -#ifdef HAVE_SELINUX - /* XXX - restrict type/role to initial state */ - if (strcmp(yytext, "TYPE") == 0) { - LEXTRACE("TYPE "); - return(TYPE); - } - if (strcmp(yytext, "ROLE") == 0) { - LEXTRACE("ROLE "); - return(ROLE); - } -#endif /* HAVE_SELINUX */ - fill(yytext, yyleng); - LEXTRACE("ALIAS "); - return(ALIAS); - } - -(#[0-9-]+|{WORD}) { - /* username/uid that user can run command as */ - fill(yytext, yyleng); - LEXTRACE("WORD(3) "); - return(WORD); - } - -#[^0-9-].*\n { - BEGIN INITIAL; - ++sudolineno; - LEXTRACE("\n"); - return(COMMENT); - } - -\) { - BEGIN INITIAL; - } - -sudoedit { - BEGIN GOTCMND; - LEXTRACE("COMMAND "); - fill_cmnd(yytext, yyleng); - } /* sudo -e */ - -\/(\\[\,:= \t#]|[^\,:=\\ \t\n#])+ { - /* directories can't have args... */ - if (yytext[yyleng - 1] == '/') { - LEXTRACE("COMMAND "); - fill_cmnd(yytext, yyleng); - return(COMMAND); - } else { - BEGIN GOTCMND; - LEXTRACE("COMMAND "); - fill_cmnd(yytext, yyleng); - } - } /* a pathname */ - -{WORD} { - /* a word */ - fill(yytext, yyleng); - LEXTRACE("WORD(4) "); - return(WORD); - } - -, { - LEXTRACE(", "); - return(','); - } /* return ',' */ - -= { - LEXTRACE("= "); - return('='); - } /* return '=' */ - -: { - LEXTRACE(": "); - return(':'); - } /* return ':' */ - -<*>!+ { - if (yyleng % 2 == 1) - return('!'); /* return '!' */ - } - -<*>\n { - BEGIN INITIAL; - ++sudolineno; - LEXTRACE("\n"); - return(COMMENT); - } /* return newline */ - -<*>[[:blank:]]+ { /* throw away space/tabs */ - sawspace = TRUE; /* but remember for fill_args */ - } - -<*>\\[[:blank:]]*\n { - sawspace = TRUE; /* remember for fill_args */ - ++sudolineno; - LEXTRACE("\n\t"); - } /* throw away EOL after \ */ - -#.*\n { - BEGIN INITIAL; - ++sudolineno; - LEXTRACE("\n"); - return(COMMENT); - } /* return comments */ - -<*>. { - LEXTRACE("ERROR "); - return(ERROR); - } /* parse error */ - -<*><> { - if (YY_START != INITIAL) { - BEGIN INITIAL; - LEXTRACE("ERROR "); - return(ERROR); - } - yyterminate(); - } - -%% -static void -_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); - if (dst == NULL) { - yyerror("unable to allocate memory"); - return; - } - yylval.string = dst; - - /* 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]; - } - dst[j] = '\0'; -} - -static void -append(src, len) - char *src; - int len; -{ - int olen = 0; - - if (yylval.string != NULL) - olen = strlen(yylval.string); - - _fill(src, len, olen); -} - -static void -fill_cmnd(s, len) - char *s; - int len; -{ - arg_len = arg_size = 0; - - yylval.command.cmnd = (char *) malloc(++len); - if (yylval.command.cmnd == NULL) { - yyerror("unable to allocate memory"); - return; - } - - /* copy the string and NULL-terminate it (escapes handled by fnmatch) */ - (void) strlcpy(yylval.command.cmnd, s, len); - - yylval.command.args = NULL; -} - -static void -fill_args(s, len, addspace) - char *s; - int len; - int addspace; -{ - int new_len; - char *p; - - if (yylval.command.args == NULL) { - addspace = 0; - new_len = len; - } else - new_len = arg_len + len + addspace; - - if (new_len >= arg_size) { - /* Allocate more space than we need for subsequent args */ - while (new_len >= (arg_size += COMMANDARGINC)) - ; - - p = yylval.command.args ? - (char *) realloc(yylval.command.args, arg_size) : - (char *) malloc(arg_size); - if (p == NULL) { - efree(yylval.command.args); - yyerror("unable to allocate memory"); - return; - } else - yylval.command.args = p; - } - - /* Efficiently append the arg (with a leading space if needed). */ - p = yylval.command.args + arg_len; - if (addspace) - *p++ = ' '; - if (strlcpy(p, s, arg_size - (p - yylval.command.args)) != len) - yyerror("fill_args: buffer overflow"); /* paranoia */ - arg_len = new_len; -} - -/* - * Check to make sure an IPv6 address does not contain multiple instances - * of the string "::". Assumes strlen(s) >= 1. - * Returns TRUE if address is valid else FALSE. - */ -static int -ipv6_valid(s) - const char *s; -{ - int nmatch = 0; - - for (; *s != '\0'; s++) { - if (s[0] == ':' && s[1] == ':') { - if (++nmatch > 1) - break; - } - if (s[0] == '/') - nmatch = 0; /* reset if we hit netmask */ - } - - return (nmatch <= 1); -} - -int -yywrap() -{ - - /* Free space used by the aliases unless called by testsudoers. */ - if (clearaliases) - reset_aliases(); - - return(TRUE); -} diff --git a/parse.yacc b/parse.yacc deleted file mode 100644 index 93871b2..0000000 --- a/parse.yacc +++ /dev/null @@ -1,1418 +0,0 @@ -%{ -/* - * Copyright (c) 1996, 1998-2004, 2007 - * 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. - * - * 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. - */ - -/* - * XXX - the whole opFOO naming thing is somewhat bogus. - * - * XXX - the way things are stored for printmatches is stupid, - * they should be stored as elements in an array and then - * list_matches() can format things the way it wants. - */ - -#include - -#include -#include -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif /* STDC_HEADERS */ -#ifdef HAVE_STRING_H -# include -#else -# ifdef HAVE_STRINGS_H -# include -# endif -#endif /* HAVE_STRING_H */ -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ -#include -#if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__) -# include -#endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */ -#ifdef HAVE_LSEARCH -# include -#endif /* HAVE_LSEARCH */ -#include - -#include "sudo.h" -#include "parse.h" - -#ifndef HAVE_LSEARCH -#include "emul/search.h" -#endif /* HAVE_LSEARCH */ - -#ifndef lint -__unused static const char rcsid[] = "$Sudo: parse.yacc,v 1.204.2.13 2008/02/27 20:34:42 millert Exp $"; -#endif /* lint */ - -/* - * We must define SIZE_MAX for yacc's skeleton.c. - * If there is no SIZE_MAX or SIZE_T_MAX we have to assume that size_t - * could be signed (as it is on SunOS 4.x). - */ -#ifndef SIZE_MAX -# ifdef SIZE_T_MAX -# define SIZE_MAX SIZE_T_MAX -# else -# define SIZE_MAX INT_MAX -# endif /* SIZE_T_MAX */ -#endif /* SIZE_MAX */ - -/* - * Globals - */ -extern int sudolineno, parse_error; -int errorlineno = -1; -int clearaliases = TRUE; -int printmatches = FALSE; -int pedantic = FALSE; -int keepall = FALSE; -int quiet = FALSE; -int used_runas = FALSE; - -/* - * Alias types - */ -#define HOST_ALIAS 1 -#define CMND_ALIAS 2 -#define USER_ALIAS 3 -#define RUNAS_ALIAS 4 - -#define SETMATCH(_var, _val) do { \ - if ((_var) == UNSPEC || (_val) != NOMATCH) \ - (_var) = (_val); \ -} while (0) - -#define SETNMATCH(_var, _val) do { \ - if ((_val) != NOMATCH) \ - (_var) = ! (_val); \ - else if ((_var) == UNSPEC) \ - (_var) = NOMATCH; \ -} while (0) - -#define SETENV_RESET \ - if (setenv_ok == IMPLIED) setenv_ok = def_setenv ? TRUE : UNSPEC - -/* - * The matching stack, initial space allocated in init_parser(). - */ -struct matchstack *match; -int top = 0, stacksize = 0; - -#define push \ - do { \ - if (top >= stacksize) { \ - while ((stacksize += STACKINCREMENT) < top); \ - match = (struct matchstack *) erealloc3(match, stacksize, sizeof(struct matchstack)); \ - } \ - match[top].user = UNSPEC; \ - match[top].cmnd = UNSPEC; \ - match[top].host = UNSPEC; \ - match[top].runas = UNSPEC; \ - match[top].nopass = def_authenticate ? UNSPEC : TRUE; \ - match[top].noexec = def_noexec ? TRUE : UNSPEC; \ - match[top].setenv = def_setenv ? TRUE : UNSPEC; \ - match[top].role = NULL; \ - match[top].type = NULL; \ - top++; \ - } while (0) - -#define pushcp \ - do { \ - if (top >= stacksize) { \ - while ((stacksize += STACKINCREMENT) < top); \ - match = (struct matchstack *) erealloc3(match, stacksize, sizeof(struct matchstack)); \ - } \ - match[top].user = match[top-1].user; \ - match[top].cmnd = match[top-1].cmnd; \ - match[top].host = match[top-1].host; \ - match[top].runas = match[top-1].runas; \ - match[top].nopass = match[top-1].nopass; \ - match[top].noexec = match[top-1].noexec; \ - match[top].setenv = match[top-1].setenv; \ - match[top].role = estrdup(match[top-1].role); \ - match[top].type = estrdup(match[top-1].type); \ - top++; \ - } while (0) - -#define pop \ - do { \ - if (top == 0) \ - yyerror("matching stack underflow"); \ - else { \ - efree(match[top-1].role); \ - efree(match[top-1].type); \ - top--; \ - } \ - } while (0) - - -/* - * For testing if foo_matches variable was set to TRUE or FALSE - */ -#define MATCHED(_v) ((_v) >= 0) - -/* - * Shortcuts for append() - */ -#define append_cmnd(s, p) append(s, &cm_list[cm_list_len].cmnd, \ - &cm_list[cm_list_len].cmnd_len, &cm_list[cm_list_len].cmnd_size, p) - -#define append_runas(s, p) append(s, &cm_list[cm_list_len].runas, \ - &cm_list[cm_list_len].runas_len, &cm_list[cm_list_len].runas_size, p) - -#define append_role(s, p) append(s, &cm_list[cm_list_len].role, \ - &cm_list[cm_list_len].role_len, &cm_list[cm_list_len].role_size, p) - -#define append_type(s, p) append(s, &cm_list[cm_list_len].type, \ - &cm_list[cm_list_len].type_len, &cm_list[cm_list_len].type_size, p) - -#define append_entries(s, p) append(s, &ga_list[ga_list_len-1].entries, \ - &ga_list[ga_list_len-1].entries_len, \ - &ga_list[ga_list_len-1].entries_size, p) - -/* - * The stack for printmatches. A list of allowed commands for the user. - */ -static struct command_match *cm_list = NULL; -static size_t cm_list_len = 0, cm_list_size = 0; - -/* - * List of Cmnd_Aliases and expansions for `sudo -l' - */ -static int in_alias = FALSE; -static size_t ga_list_len = 0, ga_list_size = 0; -static struct generic_alias *ga_list = NULL; - -/* - * Does this Defaults list pertain to this user? - */ -static int defaults_matches = FALSE; - -/* - * Local protoypes - */ -static int add_alias __P((char *, int, int)); -static void append __P((char *, char **, size_t *, size_t *, char *)); -static void expand_ga_list __P((void)); -static void expand_match_list __P((void)); -static aliasinfo *find_alias __P((char *, int)); -static void more_aliases __P((void)); - void init_parser __P((void)); - void yyerror __P((char *)); - -void -yyerror(s) - char *s; -{ - /* Save the line the first error occurred on. */ - if (errorlineno == -1) - errorlineno = sudolineno ? sudolineno - 1 : 0; - if (s && !quiet) { -#ifndef TRACELEXER - (void) fprintf(stderr, ">>> sudoers file: %s, line %d <<<\n", s, - sudolineno ? sudolineno - 1 : 0); -#else - (void) fprintf(stderr, "<*> "); -#endif - } - parse_error = TRUE; -} -%} - -%union { - char *string; - int BOOLEAN; - struct sudo_command command; - int tok; - struct selinux_info seinfo; -} - -%start file /* special start symbol */ -%token COMMAND /* absolute pathname w/ optional args */ -%token ALIAS /* an UPPERCASE alias name */ -%token DEFVAR /* a Defaults variable name */ -%token NTWKADDR /* w.x.y.z or ipv6 address */ -%token NETGROUP /* a netgroup (+NAME) */ -%token USERGROUP /* a usergroup (%NAME) */ -%token WORD /* a word */ -%token DEFAULTS /* Defaults entry */ -%token DEFAULTS_HOST /* Host-specific defaults entry */ -%token DEFAULTS_USER /* User-specific defaults entry */ -%token DEFAULTS_RUNAS /* Runas-specific defaults entry */ -%token RUNAS /* ( runas_list ) */ -%token NOPASSWD /* no passwd req for command */ -%token PASSWD /* passwd req for command (default) */ -%token NOEXEC /* preload dummy execve() for cmnd */ -%token EXEC /* don't preload dummy execve() */ -%token SETENV /* user may set environment for cmnd */ -%token NOSETENV /* user may not set environment */ -%token ALL /* ALL keyword */ -%token COMMENT /* comment and/or carriage return */ -%token HOSTALIAS /* Host_Alias keyword */ -%token CMNDALIAS /* Cmnd_Alias keyword */ -%token USERALIAS /* User_Alias keyword */ -%token RUNASALIAS /* Runas_Alias keyword */ -%token ':' '=' ',' '!' '+' '-' /* union member tokens */ -%token ERROR -%token TYPE /* SELinux type */ -%token ROLE /* SELinux role */ - -/* - * NOTE: these are not true booleans as there are actually 4 possible values: - * 1) TRUE (positive match) - * 0) FALSE (negative match due to a '!' somewhere) - * -1) NOMATCH (don't change the value of *_matches) - * -2) UNSPEC (uninitialized value) - */ -%type cmnd -%type host -%type runasuser -%type oprunasuser -%type runaslist -%type user -%type selinux -%type rolespec -%type typespec - -%% - -file : entry - | file entry - ; - -entry : COMMENT - { ; } - | error COMMENT - { yyerrok; } - | { push; } userlist privileges { - while (top && user_matches != TRUE) - pop; - } - | USERALIAS useraliases - { ; } - | HOSTALIAS hostaliases - { ; } - | CMNDALIAS cmndaliases - { ; } - | RUNASALIAS runasaliases - { ; } - | defaults_line - { ; } - ; - -defaults_line : defaults_type defaults_list - ; - -defaults_type : DEFAULTS { - defaults_matches = TRUE; - } - | DEFAULTS_USER { push; } userlist { - defaults_matches = user_matches; - pop; - } - | DEFAULTS_RUNAS { push; } runaslist { - defaults_matches = $3 == TRUE; - pop; - } - | DEFAULTS_HOST { push; } hostlist { - defaults_matches = host_matches; - pop; - } - ; - -defaults_list : defaults_entry - | defaults_entry ',' defaults_list - ; - -defaults_entry : DEFVAR { - if (defaults_matches == TRUE && - !set_default($1, NULL, TRUE)) { - yyerror(NULL); - YYERROR; - } - efree($1); - } - | '!' DEFVAR { - if (defaults_matches == TRUE && - !set_default($2, NULL, FALSE)) { - yyerror(NULL); - YYERROR; - } - efree($2); - } - | DEFVAR '=' WORD { - if (defaults_matches == TRUE && - !set_default($1, $3, TRUE)) { - yyerror(NULL); - YYERROR; - } - efree($1); - efree($3); - } - | DEFVAR '+' WORD { - if (defaults_matches == TRUE && - !set_default($1, $3, '+')) { - yyerror(NULL); - YYERROR; - } - efree($1); - efree($3); - } - | DEFVAR '-' WORD { - if (defaults_matches == TRUE && - !set_default($1, $3, '-')) { - yyerror(NULL); - YYERROR; - } - efree($1); - efree($3); - } - ; - -privileges : privilege - | privileges ':' privilege - ; - -privilege : hostlist '=' cmndspeclist { - /* - * We already did a push if necessary in - * cmndspec so just reset some values so - * the next 'privilege' gets a clean slate. - */ - host_matches = UNSPEC; - runas_matches = UNSPEC; - no_passwd = def_authenticate ? UNSPEC : TRUE; - no_execve = def_noexec ? TRUE : UNSPEC; - setenv_ok = def_setenv ? TRUE : UNSPEC; -#ifdef HAVE_SELINUX - efree(match[top-1].role); - match[top-1].role = NULL; - efree(match[top-1].type); - match[top-1].type = NULL; -#endif - } - ; - -ophost : host { - SETMATCH(host_matches, $1); - } - | '!' host { - SETNMATCH(host_matches, $2); - } - ; - -host : ALL { - $$ = TRUE; - } - | NTWKADDR { - if (addr_matches($1)) - $$ = TRUE; - else - $$ = NOMATCH; - efree($1); - } - | NETGROUP { - if (netgr_matches($1, user_host, user_shost, NULL)) - $$ = TRUE; - else - $$ = NOMATCH; - efree($1); - } - | WORD { - if (hostname_matches(user_shost, user_host, $1) == 0) - $$ = TRUE; - else - $$ = NOMATCH; - efree($1); - } - | ALIAS { - aliasinfo *aip = find_alias($1, HOST_ALIAS); - - /* could be an all-caps hostname */ - if (aip) - $$ = aip->val; - else if (strcasecmp(user_shost, $1) == 0) - $$ = TRUE; - else { - if (pedantic) { - (void) fprintf(stderr, - "%s: undeclared Host_Alias `%s' referenced near line %d\n", - (pedantic == 1) ? "Warning" : "Error", $1, sudolineno); - if (pedantic > 1) { - yyerror(NULL); - YYERROR; - } - } - $$ = NOMATCH; - } - efree($1); - } - ; - -cmndspeclist : cmndspec - | cmndspeclist ',' cmndspec - ; - -cmndspec : { SETENV_RESET; } runasspec selinux cmndtag opcmnd { -#ifdef HAVE_SELINUX - /* Replace inherited role/type as needed. */ - if ($3.role != NULL) { - efree(match[top-1].role); - match[top-1].role = $3.role; - } - if ($3.type != NULL) { - efree(match[top-1].type); - match[top-1].type = $3.type; - } -#endif - /* - * Push the entry onto the stack if it is worth - * saving and reset cmnd_matches for next cmnd. - * - * We need to save at least one entry on - * the stack so sudoers_lookup() can tell that - * the user was listed in sudoers. Also, we - * need to be able to tell whether or not a - * user was listed for this specific host. - * - * If keepall is set and the user matches then - * we need to keep entries around too... - */ - if (MATCHED(user_matches) && - MATCHED(host_matches) && - MATCHED(cmnd_matches) && - MATCHED(runas_matches)) - pushcp; - else if (MATCHED(user_matches) && (top == 1 || - (top == 2 && MATCHED(host_matches) && - !MATCHED(match[0].host)))) - pushcp; - else if (user_matches == TRUE && keepall) - pushcp; - - cmnd_matches = UNSPEC; - } - ; - -opcmnd : cmnd { - SETMATCH(cmnd_matches, $1); - } - | '!' { - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries("!", ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_cmnd("!", NULL); - } - } cmnd { - SETNMATCH(cmnd_matches, $3); - } - ; - -rolespec : ROLE '=' WORD { -#ifdef HAVE_SELINUX - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE && runas_matches == TRUE) - append_role($3, NULL); - $$ = $3; -#else - free($3); - $$ = NULL; -#endif /* HAVE_SELINUX */ - } - ; - -typespec : TYPE '=' WORD { -#ifdef HAVE_SELINUX - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE && runas_matches == TRUE) - append_type($3, NULL); - $$ = $3; -#else - free($3); - $$ = NULL; -#endif /* HAVE_SELINUX */ - } - ; - -selinux : /* empty */ { -#ifdef HAVE_SELINUX - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE && runas_matches == TRUE) { - /* Inherit role. */ - cm_list[cm_list_len].role = - estrdup(cm_list[cm_list_len-1].role); - cm_list[cm_list_len].role_len = - cm_list[cm_list_len-1].role_len; - cm_list[cm_list_len].role_size = - cm_list[cm_list_len-1].role_len + 1; - /* Inherit type. */ - cm_list[cm_list_len].type = - estrdup(cm_list[cm_list_len-1].type); - cm_list[cm_list_len].type_len = - cm_list[cm_list_len-1].type_len; - cm_list[cm_list_len].type_size = - cm_list[cm_list_len-1].type_len + 1; - } -#endif /* HAVE_SELINUX */ - $$.role = NULL; - $$.type = NULL; - } - | rolespec { -#ifdef HAVE_SELINUX - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE && runas_matches == TRUE) { - /* Inherit type. */ - cm_list[cm_list_len].type = - estrdup(cm_list[cm_list_len-1].type); - cm_list[cm_list_len].type_len = - cm_list[cm_list_len-1].type_len; - cm_list[cm_list_len].type_size = - cm_list[cm_list_len-1].type_len + 1; - } -#endif /* HAVE_SELINUX */ - $$.role = $1; - $$.type = NULL; - } - | typespec { -#ifdef HAVE_SELINUX - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE && runas_matches == TRUE) { - /* Inherit role. */ - cm_list[cm_list_len].role = - estrdup(cm_list[cm_list_len-1].role); - cm_list[cm_list_len].role_len = - cm_list[cm_list_len-1].role_len; - cm_list[cm_list_len].role_size = - cm_list[cm_list_len-1].role_len + 1; - } -#endif /* HAVE_SELINUX */ - $$.type = $1; - $$.role = NULL; - } - | rolespec typespec { - $$.role = $1; - $$.type = $2; - } - | typespec rolespec { - $$.type = $1; - $$.role = $2; - } - ; - -runasspec : /* empty */ { - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) { - if (runas_matches == UNSPEC) { - cm_list[cm_list_len].runas_len = 0; - } else { - /* Inherit runas data. */ - cm_list[cm_list_len].runas = - estrdup(cm_list[cm_list_len-1].runas); - cm_list[cm_list_len].runas_len = - cm_list[cm_list_len-1].runas_len; - cm_list[cm_list_len].runas_size = - cm_list[cm_list_len-1].runas_len + 1; - } - } - /* - * If this is the first entry in a command list - * then check against default runas user. - */ - if (runas_matches == UNSPEC) { - runas_matches = userpw_matches(def_runas_default, - *user_runas, runas_pw) ? TRUE : NOMATCH; - } - } - | RUNAS runaslist { - runas_matches = $2; - } - ; - -runaslist : oprunasuser { ; } - | runaslist ',' oprunasuser { - /* Later entries override earlier ones. */ - if ($3 != NOMATCH) - $$ = $3; - else - $$ = $1; - } - ; - -oprunasuser : runasuser { ; } - | '!' { - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries("!", ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas("!", ", "); - } - } runasuser { - /* Set $$ to the negation of runasuser */ - $$ = ($3 == NOMATCH ? NOMATCH : ! $3); - } - ; - -runasuser : WORD { - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries($1, ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas($1, ", "); - } - if (userpw_matches($1, *user_runas, runas_pw)) - $$ = TRUE; - else - $$ = NOMATCH; - efree($1); - used_runas = TRUE; - } - | USERGROUP { - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries($1, ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas($1, ", "); - } - if (usergr_matches($1, *user_runas, runas_pw)) - $$ = TRUE; - else - $$ = NOMATCH; - efree($1); - used_runas = TRUE; - } - | NETGROUP { - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries($1, ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas($1, ", "); - } - if (netgr_matches($1, NULL, NULL, *user_runas)) - $$ = TRUE; - else - $$ = NOMATCH; - efree($1); - used_runas = TRUE; - } - | ALIAS { - aliasinfo *aip = find_alias($1, RUNAS_ALIAS); - - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries($1, ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas($1, ", "); - } - /* could be an all-caps username */ - if (aip) - $$ = aip->val; - else if (strcmp($1, *user_runas) == 0) - $$ = TRUE; - else { - if (pedantic) { - (void) fprintf(stderr, - "%s: undeclared Runas_Alias `%s' referenced near line %d\n", - (pedantic == 1) ? "Warning" : "Error", $1, sudolineno); - if (pedantic > 1) { - yyerror(NULL); - YYERROR; - } - } - $$ = NOMATCH; - } - efree($1); - used_runas = TRUE; - } - | ALL { - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries("ALL", ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas("ALL", ", "); - } - $$ = TRUE; - } - ; - -cmndtag : /* empty */ { - /* Inherit {NO,}{PASSWD,EXEC,SETENV} status. */ - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) { - if (no_passwd == TRUE) - cm_list[cm_list_len].nopasswd = TRUE; - else - cm_list[cm_list_len].nopasswd = FALSE; - if (no_execve == TRUE) - cm_list[cm_list_len].noexecve = TRUE; - else - cm_list[cm_list_len].noexecve = FALSE; - if (setenv_ok == TRUE) - cm_list[cm_list_len].setenv = TRUE; - else - cm_list[cm_list_len].setenv = FALSE; - } - } - | cmndtag NOPASSWD { - no_passwd = TRUE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].nopasswd = TRUE; - } - | cmndtag PASSWD { - no_passwd = FALSE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].nopasswd = FALSE; - } - | cmndtag NOEXEC { - no_execve = TRUE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].noexecve = TRUE; - } - | cmndtag EXEC { - no_execve = FALSE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].noexecve = FALSE; - } - | cmndtag SETENV { - setenv_ok = TRUE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].setenv = TRUE; - } - | cmndtag NOSETENV { - setenv_ok = FALSE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].setenv = FALSE; - } - ; - -cmnd : ALL { - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries("ALL", ", "); - else if (host_matches == TRUE && - user_matches == TRUE) { - append_cmnd("ALL", NULL); - expand_match_list(); - } - } - /* sudo "ALL" implies the SETENV tag */ - if (setenv_ok == UNSPEC) - setenv_ok = IMPLIED; - - efree(safe_cmnd); - safe_cmnd = NULL; - $$ = TRUE; - } - | ALIAS { - aliasinfo *aip; - - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries($1, ", "); - else if (host_matches == TRUE && - user_matches == TRUE) { - append_cmnd($1, NULL); - expand_match_list(); - } - } - - if ((aip = find_alias($1, CMND_ALIAS))) - $$ = aip->val; - else { - if (pedantic) { - (void) fprintf(stderr, - "%s: undeclared Cmnd_Alias `%s' referenced near line %d\n", - (pedantic == 1) ? "Warning" : "Error", $1, sudolineno); - if (pedantic > 1) { - yyerror(NULL); - YYERROR; - } - } - $$ = NOMATCH; - } - efree($1); - } - | COMMAND { - if (printmatches == TRUE) { - if (in_alias == TRUE) { - append_entries($1.cmnd, ", "); - if ($1.args) - append_entries($1.args, " "); - } - if (host_matches == TRUE && - user_matches == TRUE) { - append_cmnd($1.cmnd, NULL); - if ($1.args) - append_cmnd($1.args, " "); - expand_match_list(); - } - } - - if (command_matches($1.cmnd, $1.args)) - $$ = TRUE; - else - $$ = NOMATCH; - - efree($1.cmnd); - efree($1.args); - } - ; - -hostaliases : hostalias - | hostaliases ':' hostalias - ; - -hostalias : ALIAS { push; } '=' hostlist { - if ((MATCHED(host_matches) || pedantic) && - !add_alias($1, HOST_ALIAS, host_matches)) { - yyerror(NULL); - YYERROR; - } - pop; - } - ; - -hostlist : ophost - | hostlist ',' ophost - ; - -cmndaliases : cmndalias - | cmndaliases ':' cmndalias - ; - -cmndalias : ALIAS { - push; - if (printmatches == TRUE) { - in_alias = TRUE; - /* Allocate space for ga_list if necessary. */ - expand_ga_list(); - ga_list[ga_list_len-1].type = CMND_ALIAS; - ga_list[ga_list_len-1].alias = estrdup($1); - } - } '=' cmndlist { - if ((MATCHED(cmnd_matches) || pedantic) && - !add_alias($1, CMND_ALIAS, cmnd_matches)) { - yyerror(NULL); - YYERROR; - } - pop; - efree($1); - - if (printmatches == TRUE) - in_alias = FALSE; - } - ; - -cmndlist : opcmnd { ; } - | cmndlist ',' opcmnd - ; - -runasaliases : runasalias - | runasaliases ':' runasalias - ; - -runasalias : ALIAS { - if (printmatches == TRUE) { - in_alias = TRUE; - /* Allocate space for ga_list if necessary. */ - expand_ga_list(); - ga_list[ga_list_len-1].type = RUNAS_ALIAS; - ga_list[ga_list_len-1].alias = estrdup($1); - } - } '=' runaslist { - if (($4 != NOMATCH || pedantic) && - !add_alias($1, RUNAS_ALIAS, $4)) { - yyerror(NULL); - YYERROR; - } - efree($1); - - if (printmatches == TRUE) - in_alias = FALSE; - } - ; - -useraliases : useralias - | useraliases ':' useralias - ; - -useralias : ALIAS { push; } '=' userlist { - if ((MATCHED(user_matches) || pedantic) && - !add_alias($1, USER_ALIAS, user_matches)) { - yyerror(NULL); - YYERROR; - } - pop; - efree($1); - } - ; - -userlist : opuser - | userlist ',' opuser - ; - -opuser : user { - SETMATCH(user_matches, $1); - } - | '!' user { - SETNMATCH(user_matches, $2); - } - ; - -user : WORD { - if (userpw_matches($1, user_name, sudo_user.pw)) - $$ = TRUE; - else - $$ = NOMATCH; - efree($1); - } - | USERGROUP { - if (usergr_matches($1, user_name, sudo_user.pw)) - $$ = TRUE; - else - $$ = NOMATCH; - efree($1); - } - | NETGROUP { - if (netgr_matches($1, NULL, NULL, user_name)) - $$ = TRUE; - else - $$ = NOMATCH; - efree($1); - } - | ALIAS { - aliasinfo *aip = find_alias($1, USER_ALIAS); - - /* could be an all-caps username */ - if (aip) - $$ = aip->val; - else if (strcmp($1, user_name) == 0) - $$ = TRUE; - else { - if (pedantic) { - (void) fprintf(stderr, - "%s: undeclared User_Alias `%s' referenced near line %d\n", - (pedantic == 1) ? "Warning" : "Error", $1, sudolineno); - if (pedantic > 1) { - yyerror(NULL); - YYERROR; - } - } - $$ = NOMATCH; - } - efree($1); - } - | ALL { - $$ = TRUE; - } - ; - -%% - -#define MOREALIASES (32) -aliasinfo *aliases = NULL; -size_t naliases = 0; -size_t nslots = 0; - - -/* - * Compare two aliasinfo structures, strcmp() style. - * Note that we do *not* compare their values. - */ -static int -aliascmp(a1, a2) - const VOID *a1, *a2; -{ - int r; - aliasinfo *ai1, *ai2; - - ai1 = (aliasinfo *) a1; - ai2 = (aliasinfo *) a2; - if ((r = strcmp(ai1->name, ai2->name)) == 0) - r = ai1->type - ai2->type; - - return(r); -} - -/* - * Compare two generic_alias structures, strcmp() style. - */ -static int -genaliascmp(entry, key) - const VOID *entry, *key; -{ - int r; - struct generic_alias *ga1, *ga2; - - ga1 = (struct generic_alias *) key; - ga2 = (struct generic_alias *) entry; - if ((r = strcmp(ga1->alias, ga2->alias)) == 0) - r = ga1->type - ga2->type; - - return(r); -} - - -/* - * Adds the named alias of the specified type to the aliases list. - */ -static int -add_alias(alias, type, val) - char *alias; - int type; - int val; -{ - aliasinfo ai, *aip; - size_t onaliases; - char s[512]; - - if (naliases >= nslots) - more_aliases(); - - ai.type = type; - ai.val = val; - ai.name = estrdup(alias); - onaliases = naliases; - - aip = (aliasinfo *) lsearch((VOID *)&ai, (VOID *)aliases, &naliases, - sizeof(ai), aliascmp); - if (aip == NULL) { - (void) snprintf(s, sizeof(s), "Aliases corrupted defining alias `%s'", - alias); - yyerror(s); - return(FALSE); - } - if (onaliases == naliases) { - (void) snprintf(s, sizeof(s), "Alias `%s' already defined", alias); - yyerror(s); - return(FALSE); - } - - return(TRUE); -} - -/* - * Searches for the named alias of the specified type. - */ -static aliasinfo * -find_alias(alias, type) - char *alias; - int type; -{ - aliasinfo ai; - - ai.name = alias; - ai.type = type; - - return((aliasinfo *) lfind((VOID *)&ai, (VOID *)aliases, &naliases, - sizeof(ai), aliascmp)); -} - -/* - * Allocates more space for the aliases list. - */ -static void -more_aliases() -{ - - nslots += MOREALIASES; - aliases = (aliasinfo *) erealloc3(aliases, nslots, sizeof(aliasinfo)); -} - -/* - * Lists the contents of the aliases list. - */ -void -dumpaliases() -{ - size_t n; - - for (n = 0; n < naliases; n++) { - if (aliases[n].val == -1) - continue; - - switch (aliases[n].type) { - case HOST_ALIAS: - (void) puts("HOST_ALIAS"); - break; - - case CMND_ALIAS: - (void) puts("CMND_ALIAS"); - break; - - case USER_ALIAS: - (void) puts("USER_ALIAS"); - break; - - case RUNAS_ALIAS: - (void) puts("RUNAS_ALIAS"); - break; - } - (void) printf("\t%s: %d\n", aliases[n].name, aliases[n].val); - } -} - -/* - * Lists the contents of cm_list and ga_list for `sudo -l'. - */ -void -list_matches() -{ - size_t count; - char *p; - struct generic_alias *ga, key; - - (void) printf("User %s may run the following commands on this host:\n", - user_name); - for (count = 0; count < cm_list_len; count++) { - - /* Print the runas list. */ - (void) fputs(" ", stdout); - if (cm_list[count].runas) { - (void) putchar('('); - p = strtok(cm_list[count].runas, ", "); - do { - if (p != cm_list[count].runas) - (void) fputs(", ", stdout); - - key.alias = p; - key.type = RUNAS_ALIAS; - if ((ga = (struct generic_alias *) lfind((VOID *) &key, - (VOID *) &ga_list[0], &ga_list_len, sizeof(key), genaliascmp))) - (void) fputs(ga->entries, stdout); - else - (void) fputs(p, stdout); - } while ((p = strtok(NULL, ", "))); - (void) fputs(") ", stdout); - } else { - (void) printf("(%s) ", def_runas_default); - } - -#ifdef HAVE_SELINUX - /* SELinux role and type */ - if (cm_list[count].role != NULL) - (void) printf("ROLE=%s ", cm_list[count].role); - if (cm_list[count].type != NULL) - (void) printf("TYPE=%s ", cm_list[count].type); -#endif - - /* Is execve(2) disabled? */ - if (cm_list[count].noexecve == TRUE && !def_noexec) - (void) fputs("NOEXEC: ", stdout); - else if (cm_list[count].noexecve == FALSE && def_noexec) - (void) fputs("EXEC: ", stdout); - - /* Is a password required? */ - if (cm_list[count].nopasswd == TRUE && def_authenticate) - (void) fputs("NOPASSWD: ", stdout); - else if (cm_list[count].nopasswd == FALSE && !def_authenticate) - (void) fputs("PASSWD: ", stdout); - - /* Is setenv enabled? */ - if (cm_list[count].setenv == TRUE && !def_setenv) - (void) fputs("SETENV: ", stdout); - else if (cm_list[count].setenv == FALSE && def_setenv) - (void) fputs("NOSETENV: ", stdout); - - /* Print the actual command or expanded Cmnd_Alias. */ - key.alias = cm_list[count].cmnd; - key.type = CMND_ALIAS; - if ((ga = (struct generic_alias *) lfind((VOID *) &key, - (VOID *) &ga_list[0], &ga_list_len, sizeof(key), genaliascmp))) - (void) puts(ga->entries); - else - (void) puts(cm_list[count].cmnd); - } - - /* Be nice and free up space now that we are done. */ - for (count = 0; count < ga_list_len; count++) { - efree(ga_list[count].alias); - efree(ga_list[count].entries); - } - efree(ga_list); - ga_list = NULL; - - for (count = 0; count < cm_list_len; count++) { - efree(cm_list[count].runas); - efree(cm_list[count].cmnd); - efree(cm_list[count].role); - efree(cm_list[count].type); - } - efree(cm_list); - cm_list = NULL; - cm_list_len = 0; - cm_list_size = 0; -} - -/* - * Appends a source string to the destination, optionally prefixing a separator. - */ -static void -append(src, dstp, dst_len, dst_size, separator) - char *src, **dstp; - size_t *dst_len, *dst_size; - char *separator; -{ - size_t src_len = strlen(src); - char *dst = *dstp; - - /* - * Only add the separator if there is something to separate from. - * If the last char is a '!', don't apply the separator (XXX). - */ - if (separator && dst && dst[*dst_len - 1] != '!') - src_len += strlen(separator); - else - separator = NULL; - - /* Assumes dst will be NULL if not set. */ - if (dst == NULL) { - dst = (char *) emalloc(BUFSIZ); - *dst = '\0'; - *dst_size = BUFSIZ; - *dst_len = 0; - *dstp = dst; - } - - /* Allocate more space if necessary. */ - if (*dst_size <= *dst_len + src_len) { - while (*dst_size <= *dst_len + src_len) - *dst_size += BUFSIZ; - - dst = (char *) erealloc(dst, *dst_size); - *dstp = dst; - } - - /* Copy src -> dst adding a separator if appropriate and adjust len. */ - if (separator) - (void) strlcat(dst, separator, *dst_size); - (void) strlcat(dst, src, *dst_size); - *dst_len += src_len; -} - -/* - * Frees up space used by the aliases list and resets the associated counters. - */ -void -reset_aliases() -{ - size_t n; - - if (aliases) { - for (n = 0; n < naliases; n++) - efree(aliases[n].name); - efree(aliases); - aliases = NULL; - } - naliases = nslots = 0; -} - -/* - * Increments ga_list_len, allocating more space as necessary. - */ -static void -expand_ga_list() -{ - - if (++ga_list_len >= ga_list_size) { - while ((ga_list_size += STACKINCREMENT) < ga_list_len) - ; - ga_list = (struct generic_alias *) - erealloc3(ga_list, ga_list_size, sizeof(struct generic_alias)); - } - - ga_list[ga_list_len - 1].entries = NULL; -} - -/* - * Increments cm_list_len, allocating more space as necessary. - */ -static void -expand_match_list() -{ - - if (++cm_list_len >= cm_list_size) { - while ((cm_list_size += STACKINCREMENT) < cm_list_len) - ; - if (cm_list == NULL) - cm_list_len = 0; /* start at 0 since it is a subscript */ - cm_list = (struct command_match *) - erealloc3(cm_list, cm_list_size, sizeof(struct command_match)); - } - - cm_list[cm_list_len].runas = cm_list[cm_list_len].cmnd = NULL; - cm_list[cm_list_len].type = cm_list[cm_list_len].role = NULL; - cm_list[cm_list_len].nopasswd = FALSE; - cm_list[cm_list_len].noexecve = FALSE; - cm_list[cm_list_len].setenv = FALSE; -} - -/* - * Frees up spaced used by a previous parser run and allocates new space - * for various data structures. - */ -void -init_parser() -{ - - /* Free up old data structures if we run the parser more than once. */ - if (match) { - efree(match); - match = NULL; - top = 0; - parse_error = FALSE; - used_runas = FALSE; - errorlineno = -1; - sudolineno = 1; - } - - /* Allocate space for the matching stack. */ - stacksize = STACKINCREMENT; - match = (struct matchstack *) emalloc2(stacksize, sizeof(struct matchstack)); - - /* Allocate space for the match list (for `sudo -l'). */ - if (printmatches == TRUE) - expand_match_list(); -} diff --git a/pathnames.h.in b/pathnames.h.in index 3fc3249..430f96a 100644 --- a/pathnames.h.in +++ b/pathnames.h.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: pathnames.h.in,v 1.51.2.4 2008/02/09 14:44:48 millert Exp $ + * $Sudo: pathnames.h.in,v 1.63 2008/11/10 13:07:38 millert Exp $ */ /* @@ -45,22 +45,17 @@ #define _PATH_DEFPATH "/usr/bin:/bin" #endif /* _PATH_DEFPATH */ +#ifndef _PATH_ENVIRONMENT +#define _PATH_ENVIRONMENT "/etc/environment" +#endif /* _PATH_ENVIRONMENT */ + /* - * NOTE: _PATH_SUDOERS is usually overriden by the Makefile. + * NOTE: _PATH_SUDOERS is usually overridden by the Makefile. */ #ifndef _PATH_SUDOERS #define _PATH_SUDOERS "/etc/sudoers" #endif /* _PATH_SUDOERS */ -/* - * NOTE: _PATH_SUDOERS_TMP is usually overriden by the Makefile. - * _PATH_SUDOERS_TMP *MUST* be on the same partition - * as _PATH_SUDOERS! - */ -#ifndef _PATH_SUDOERS_TMP -#define _PATH_SUDOERS_TMP "/etc/sudoers.tmp" -#endif /* _PATH_SUDOERS_TMP */ - /* * The following paths are controlled via the configure script. */ @@ -89,6 +84,10 @@ #undef _PATH_SUDO_NOEXEC #endif /* _PATH_SUDO_NOEXEC */ +#ifndef _PATH_SUDO_ASKPASS +#undef _PATH_SUDO_ASKPASS +#endif /* _PATH_SUDO_ASKPASS */ + #ifndef _PATH_VI #undef _PATH_VI #endif /* _PATH_VI */ @@ -101,10 +100,6 @@ #undef _PATH_BSHELL #endif /* _PATH_BSHELL */ -#ifndef _PATH_SUDO_SESH -#undef _PATH_SUDO_SESH -#endif /* _PATH_SUDO_SESH */ - #ifndef _PATH_TMP #define _PATH_TMP "/tmp/" #endif /* _PATH_TMP */ @@ -117,10 +112,18 @@ #define _PATH_USRTMP "/usr/tmp/" #endif /* _PATH_USRTMP */ +#ifndef _PATH_SUDO_SESH +#undef _PATH_SUDO_SESH +#endif /* _PATH_SUDO_SESH */ + #ifndef _PATH_LDAP_CONF -#define _PATH_LDAP_CONF "/etc/ldap.conf" +#undef _PATH_LDAP_CONF #endif /* _PATH_LDAP_CONF */ #ifndef _PATH_LDAP_SECRET -#define _PATH_LDAP_SECRET "/etc/ldap.secret" +#undef _PATH_LDAP_SECRET #endif /* _PATH_LDAP_SECRET */ + +#ifndef _PATH_NSSWITCH_CONF +#undef _PATH_NSSWITCH_CONF +#endif /* _PATH_NSSWITCH_CONF */ diff --git a/pwutil.c b/pwutil.c new file mode 100644 index 0000000..2fd0988 --- /dev/null +++ b/pwutil.c @@ -0,0 +1,579 @@ +/* + * Copyright (c) 1996, 1998-2005, 2007-2008 + * 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. + * + * 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. + */ + +#include + +#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_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#include + +#include "sudo.h" +#include "redblack.h" + +#ifndef lint +__unused static const char rcsid[] = "$Sudo: pwutil.c,v 1.21 2008/11/09 14:13:12 millert Exp $"; +#endif /* lint */ + +#ifdef MYPW +extern void (*my_setgrent) __P((void)); +extern void (*my_endgrent) __P((void)); +extern struct group *(*my_getgrnam) __P((const char *)); +extern struct group *(*my_getgrgid) __P((gid_t)); +#define setgrent() my_setgrent() +#define endgrent() my_endgrent() +#define getgrnam(n) my_getgrnam(n) +#define getgrgid(g) my_getgrgid(g) + +extern void (*my_setpwent) __P((void)); +extern void (*my_endpwent) __P((void)); +extern struct passwd *(*my_getpwnam) __P((const char *)); +extern struct passwd *(*my_getpwuid) __P((uid_t)); +#define setpwent() my_setpwent() +#define endpwent() my_endpwent() +#define getpwnam(n) my_getpwnam(n) +#define getpwuid(u) my_getpwuid(u) +#endif + +/* + * The passwd and group caches. + */ +static struct rbtree *pwcache_byuid, *pwcache_byname; +static struct rbtree *grcache_bygid, *grcache_byname; + +static int cmp_pwuid __P((const void *, const void *)); +static int cmp_pwnam __P((const void *, const void *)); +static int cmp_grgid __P((const void *, const void *)); +static int cmp_grnam __P((const void *, const void *)); + +/* + * Compare by uid. + */ +static int +cmp_pwuid(v1, v2) + const void *v1; + const void *v2; +{ + const struct passwd *pw1 = (const struct passwd *) v1; + const struct passwd *pw2 = (const struct passwd *) v2; + return(pw1->pw_uid - pw2->pw_uid); +} + +/* + * Compare by user name. + */ +static int +cmp_pwnam(v1, v2) + const void *v1; + const void *v2; +{ + const struct passwd *pw1 = (const struct passwd *) v1; + const struct passwd *pw2 = (const struct passwd *) v2; + return(strcmp(pw1->pw_name, pw2->pw_name)); +} + +#define FIELD_SIZE(src, name, size) \ +do { \ + if (src->name) { \ + size = strlen(src->name) + 1; \ + total += size; \ + } \ +} while (0) + +#define FIELD_COPY(src, dst, name, size) \ +do { \ + if (src->name) { \ + memcpy(cp, src->name, size); \ + dst->name = cp; \ + cp += size; \ + } \ +} while (0) + +/* + * Dynamically allocate space for a struct password and the constituent parts + * that we care about. Fills in pw_passwd from shadow file. + */ +static struct passwd * +sudo_pwdup(pw) + const struct passwd *pw; +{ + char *cp; + const char *pw_shell; + size_t nsize, psize, csize, gsize, dsize, ssize, total; + struct passwd *newpw; + + /* If shell field is empty, expand to _PATH_BSHELL. */ + pw_shell = (pw->pw_shell == NULL || pw->pw_shell[0] == '\0') + ? _PATH_BSHELL : pw->pw_shell; + + /* Allocate in one big chunk for easy freeing. */ + nsize = psize = csize = gsize = dsize = ssize = 0; + total = sizeof(struct passwd); + FIELD_SIZE(pw, pw_name, nsize); + FIELD_SIZE(pw, pw_passwd, psize); +#ifdef HAVE_LOGIN_CAP_H + FIELD_SIZE(pw, pw_class, csize); +#endif + FIELD_SIZE(pw, pw_gecos, gsize); + FIELD_SIZE(pw, pw_dir, dsize); + FIELD_SIZE(pw, pw_shell, ssize); + + if ((cp = malloc(total)) == NULL) + return(NULL); + newpw = (struct passwd *) cp; + + /* + * Copy in passwd contents and make strings relative to space + * at the end of the buffer. + */ + memcpy(newpw, pw, sizeof(struct passwd)); + cp += sizeof(struct passwd); + FIELD_COPY(pw, newpw, pw_name, nsize); + FIELD_COPY(pw, newpw, pw_passwd, psize); +#ifdef HAVE_LOGIN_CAP_H + FIELD_COPY(pw, newpw, pw_class, csize); +#endif + FIELD_COPY(pw, newpw, pw_gecos, gsize); + FIELD_COPY(pw, newpw, pw_dir, dsize); + FIELD_COPY(pw, newpw, pw_shell, ssize); + + return(newpw); +} + +/* + * Get a password entry by uid and allocate space for it. + * Fills in pw_passwd from shadow file if necessary. + */ +struct passwd * +sudo_getpwuid(uid) + uid_t uid; +{ + struct passwd key, *pw; + struct rbnode *node; + char *cp; + + key.pw_uid = uid; + if ((node = rbfind(pwcache_byuid, &key)) != NULL) { + pw = (struct passwd *) node->data; + return(pw->pw_name != NULL ? pw : NULL); + } + /* + * Cache passwd db entry if it exists or a negative response if not. + */ + if ((pw = getpwuid(uid)) != NULL) { + pw = sudo_pwdup(pw); + cp = sudo_getepw(pw); /* get shadow password */ + 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"); + 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"); + return(NULL); + } +} + +/* + * Get a password entry by name and allocate space for it. + * Fills in pw_passwd from shadow file if necessary. + */ +struct passwd * +sudo_getpwnam(name) + const char *name; +{ + struct passwd key, *pw; + struct rbnode *node; + size_t len; + char *cp; + + key.pw_name = (char *) name; + if ((node = rbfind(pwcache_byname, &key)) != NULL) { + pw = (struct passwd *) node->data; + return(pw->pw_uid != (uid_t) -1 ? pw : NULL); + } + /* + * Cache passwd db entry if it exists or a negative response if not. + */ + if ((pw = getpwnam(name)) != NULL) { + pw = sudo_pwdup(pw); + cp = sudo_getepw(pw); /* get shadow password */ + 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"); + return(pw); + } else { + len = strlen(name) + 1; + cp = emalloc(sizeof(*pw) + len); + zero_bytes(cp, sizeof(*pw)); + pw = (struct passwd *) cp; + cp += sizeof(*pw); + memcpy(cp, name, len); + 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"); + return(NULL); + } +} + +/* + * Take a uid in string form "#123" and return a faked up passwd struct. + */ +struct passwd * +sudo_fakepwnam(user, gid) + const char *user; + gid_t gid; +{ + struct passwd *pw; + struct rbnode *node; + size_t len; + + len = strlen(user); + pw = emalloc(sizeof(struct passwd) + len + 1 /* pw_name */ + + sizeof("*") /* pw_passwd */ + sizeof("") /* pw_gecos */ + + sizeof("/") /* pw_dir */ + sizeof(_PATH_BSHELL)); + zero_bytes(pw, sizeof(struct passwd)); + pw->pw_uid = (uid_t) atoi(user + 1); + pw->pw_gid = gid; + pw->pw_name = (char *)pw + sizeof(struct passwd); + memcpy(pw->pw_name, user, len + 1); + pw->pw_passwd = pw->pw_name + len + 1; + memcpy(pw->pw_passwd, "*", 2); + pw->pw_gecos = pw->pw_passwd + 2; + pw->pw_gecos[0] = '\0'; + pw->pw_dir = pw->pw_gecos + 1; + memcpy(pw->pw_dir, "/", 2); + pw->pw_shell = pw->pw_dir + 2; + memcpy(pw->pw_shell, _PATH_BSHELL, sizeof(_PATH_BSHELL)); + + /* Store by uid and by name, overwriting cached version. */ + if ((node = rbinsert(pwcache_byuid, pw)) != NULL) { + efree(node->data); + node->data = (void *) pw; + } + if ((node = rbinsert(pwcache_byname, pw)) != NULL) { + efree(node->data); + node->data = (void *) pw; + } + return(pw); +} + +/* + * Take a gid in string form "#123" and return a faked up group struct. + */ +struct group * +sudo_fakegrnam(group) + const char *group; +{ + struct group *gr; + struct rbnode *node; + size_t len; + + len = strlen(group); + gr = emalloc(sizeof(struct group) + len + 1); + zero_bytes(gr, sizeof(struct group)); + gr->gr_gid = (gid_t) atoi(group + 1); + gr->gr_name = (char *)gr + sizeof(struct group); + strlcpy(gr->gr_name, group, len + 1); + + /* Store by gid and by name, overwriting cached version. */ + if ((node = rbinsert(grcache_bygid, gr)) != NULL) { + efree(node->data); + node->data = (void *) gr; + } + if ((node = rbinsert(grcache_byname, gr)) != NULL) { + efree(node->data); + node->data = (void *) gr; + } + return(gr); +} + +void +sudo_setpwent() +{ + setpwent(); + sudo_setspent(); + if (pwcache_byuid == NULL) + pwcache_byuid = rbcreate(cmp_pwuid); + if (pwcache_byname == NULL) + pwcache_byname = rbcreate(cmp_pwnam); +} + +#ifdef PURIFY +static void pw_free __P((void *)); + +void +sudo_freepwcache() +{ + if (pwcache_byuid != NULL) { + rbdestroy(pwcache_byuid, pw_free); + pwcache_byuid = NULL; + } + if (pwcache_byname != NULL) { + rbdestroy(pwcache_byname, NULL); + pwcache_byname = NULL; + } +} + +static void +pw_free(v) + void *v; +{ + struct passwd *pw = (struct passwd *) v; + + if (pw->pw_passwd != NULL) { + zero_bytes(pw->pw_passwd, strlen(pw->pw_passwd)); + efree(pw->pw_passwd); + } + efree(pw); +} +#endif /* PURIFY */ + +void +sudo_endpwent() +{ + endpwent(); + sudo_endspent(); +#ifdef PURIFY + sudo_freepwcache(); +#endif +} + +/* + * Compare by gid. + */ +static int +cmp_grgid(v1, v2) + const void *v1; + const void *v2; +{ + const struct group *grp1 = (const struct group *) v1; + const struct group *grp2 = (const struct group *) v2; + return(grp1->gr_gid - grp2->gr_gid); +} + +/* + * Compare by group name. + */ +static int +cmp_grnam(v1, v2) + const void *v1; + const void *v2; +{ + const struct group *grp1 = (const struct group *) v1; + const struct group *grp2 = (const struct group *) v2; + return(strcmp(grp1->gr_name, grp2->gr_name)); +} + +struct group * +sudo_grdup(gr) + const struct group *gr; +{ + char *cp; + size_t nsize, psize, nmem, total, len; + struct group *newgr; + + /* Allocate in one big chunk for easy freeing. */ + nsize = psize = nmem = 0; + total = sizeof(struct group); + FIELD_SIZE(gr, gr_name, nsize); + FIELD_SIZE(gr, gr_passwd, psize); + if (gr->gr_mem) { + for (nmem = 0; gr->gr_mem[nmem] != NULL; nmem++) + total += strlen(gr->gr_mem[nmem]) + 1; + nmem++; + total += sizeof(char *) * nmem; + } + if ((cp = malloc(total)) == NULL) + return(NULL); + newgr = (struct group *)cp; + + /* + * Copy in group contents and make strings relative to space + * at the end of the buffer. Note that gr_mem must come + * immediately after struct group to guarantee proper alignment. + */ + (void)memcpy(newgr, gr, sizeof(struct group)); + cp += sizeof(struct group); + if (gr->gr_mem) { + newgr->gr_mem = (char **)cp; + cp += sizeof(char *) * nmem; + for (nmem = 0; gr->gr_mem[nmem] != NULL; nmem++) { + len = strlen(gr->gr_mem[nmem]) + 1; + memcpy(cp, gr->gr_mem[nmem], len); + newgr->gr_mem[nmem] = cp; + cp += len; + } + newgr->gr_mem[nmem] = NULL; + } + FIELD_COPY(gr, newgr, gr_passwd, psize); + FIELD_COPY(gr, newgr, gr_name, nsize); + + return(newgr); +} + +/* + * Get a group entry by gid and allocate space for it. + */ +struct group * +sudo_getgrgid(gid) + gid_t gid; +{ + struct group key, *gr; + struct rbnode *node; + + key.gr_gid = gid; + if ((node = rbfind(grcache_bygid, &key)) != NULL) { + gr = (struct group *) node->data; + return(gr->gr_name != NULL ? gr : NULL); + } + /* + * Cache group db entry if it exists or a negative response if not. + */ + 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"); + 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"); + return(NULL); + } +} + +/* + * Get a group entry by name and allocate space for it. + */ +struct group * +sudo_getgrnam(name) + const char *name; +{ + struct group key, *gr; + struct rbnode *node; + size_t len; + char *cp; + + key.gr_name = (char *) name; + if ((node = rbfind(grcache_byname, &key)) != NULL) { + gr = (struct group *) node->data; + return(gr->gr_gid != (gid_t) -1 ? gr : NULL); + } + /* + * Cache group db entry if it exists or a negative response if not. + */ + 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"); + return(gr); + } else { + len = strlen(name) + 1; + cp = emalloc(sizeof(*gr) + len); + zero_bytes(cp, sizeof(*gr)); + gr = (struct group *) cp; + cp += sizeof(*gr); + memcpy(cp, name, len); + 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"); + return(NULL); + } +} + +void +sudo_setgrent() +{ + setgrent(); + if (grcache_bygid == NULL) + grcache_bygid = rbcreate(cmp_grgid); + if (grcache_byname == NULL) + grcache_byname = rbcreate(cmp_grnam); +} + +#ifdef PURIFY +void +sudo_freegrcache() +{ + if (grcache_bygid != NULL) { + rbdestroy(grcache_bygid, free); + grcache_bygid = NULL; + } + if (grcache_byname != NULL) { + rbdestroy(grcache_byname, NULL); + grcache_byname = NULL; + } +} +#endif /* PURIFY */ + +void +sudo_endgrent() +{ + endgrent(); +#ifdef PURIFY + sudo_freegrcache(); +#endif +} diff --git a/redblack.c b/redblack.c new file mode 100644 index 0000000..555e938 --- /dev/null +++ b/redblack.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2004-2005, 2007 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. + */ + +/* + * Adapted from the following code written by Emin Martinian: + * http://web.mit.edu/~emin/www/source_code/red_black_tree/index.html + * + * Copyright (c) 2001 Emin Martinian + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that neither the name of Emin + * Martinian nor the names of any contributors are be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ + +#include "sudo.h" +#include "redblack.h" + +#ifndef lint +__unused static const char rcsid[] = "$Sudo: redblack.c,v 1.10 2008/11/22 15:01:25 millert Exp $"; +#endif /* lint */ + +static void rbrepair __P((struct rbtree *, struct rbnode *)); +static void rotate_left __P((struct rbtree *, struct rbnode *)); +static void rotate_right __P((struct rbtree *, struct rbnode *)); +static void _rbdestroy __P((struct rbtree *, struct rbnode *, + void (*)(void *))); + +/* + * Red-Black tree, see http://en.wikipedia.org/wiki/Red-black_tree + * + * A red-black tree is a binary search tree where each node has a color + * attribute, the value of which is either red or black. Essentially, it + * is just a convenient way to express a 2-3-4 binary search tree where + * the color indicates whether the node is part of a 3-node or a 4-node. + * 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 + * number of black nodes. + */ + +/* + * Create a red black tree struct using the specified compare routine. + * Allocates and returns the initialized (empty) tree. + */ +struct rbtree * +rbcreate(compar) + int (*compar)__P((const void *, const void*)); +{ + struct rbtree *tree; + + tree = (struct rbtree *) emalloc(sizeof(*tree)); + tree->compar = compar; + + /* + * We use a self-referencing sentinel node called nil to simplify the + * code by avoiding the need to check for NULL pointers. + */ + tree->nil.left = tree->nil.right = tree->nil.parent = &tree->nil; + tree->nil.color = black; + tree->nil.data = NULL; + + /* + * Similarly, the fake root node keeps us from having to worry + * about splitting the root. + */ + tree->root.left = tree->root.right = tree->root.parent = &tree->nil; + tree->root.color = black; + tree->root.data = NULL; + + return(tree); +} + +/* + * Perform a left rotation starting at node. + */ +static void +rotate_left(tree, node) + struct rbtree *tree; + struct rbnode *node; +{ + struct rbnode *child; + + child = node->right; + node->right = child->left; + + if (child->left != rbnil(tree)) + child->left->parent = node; + child->parent = node->parent; + + if (node == node->parent->left) + node->parent->left = child; + else + node->parent->right = child; + child->left = node; + node->parent = child; +} + +/* + * Perform a right rotation starting at node. + */ +static void +rotate_right(tree, node) + struct rbtree *tree; + struct rbnode *node; +{ + struct rbnode *child; + + child = node->left; + node->left = child->right; + + if (child->right != rbnil(tree)) + child->right->parent = node; + child->parent = node->parent; + + if (node == node->parent->left) + node->parent->left = child; + else + node->parent->right = child; + child->right = node; + node->parent = child; +} + +/* + * Insert data pointer into a redblack tree. + * Returns a NULL pointer on success. If a node matching "data" + * already exists, a pointer to the existant node is returned. + */ +struct rbnode * +rbinsert(tree, data) + struct rbtree *tree; + void *data; +{ + struct rbnode *node = rbfirst(tree); + struct rbnode *parent = rbroot(tree); + int res; + + /* Find correct insertion point. */ + while (node != rbnil(tree)) { + parent = node; + if ((res = tree->compar(data, node->data)) == 0) + return(node); + node = res < 0 ? node->left : node->right; + } + + node = (struct rbnode *) emalloc(sizeof(*node)); + node->data = data; + node->left = node->right = rbnil(tree); + node->parent = parent; + if (parent == rbroot(tree) || tree->compar(data, parent->data) < 0) + parent->left = node; + else + parent->right = node; + node->color = red; + + /* + * If the parent node is black we are all set, if it is red we have + * the following possible cases to deal with. We iterate through + * the rest of the tree to make sure none of the required properties + * is violated. + * + * 1) The uncle is red. We repaint both the parent and uncle black + * and repaint the grandparent node red. + * + * 2) The uncle is black and the new node is the right child of its + * parent, and the parent in turn is the left child of its parent. + * We do a left rotation to switch the roles of the parent and + * child, relying on further iterations to fixup the old parent. + * + * 3) The uncle is black and the new node is the left child of its + * parent, and the parent in turn is the left child of its parent. + * We switch the colors of the parent and grandparent and perform + * a right rotation around the grandparent. This makes the former + * parent the parent of the new node and the former grandparent. + * + * Note that because we use a sentinel for the root node we never + * need to worry about replacing the root. + */ + while (node->parent->color == red) { + struct rbnode *uncle; + if (node->parent == node->parent->parent->left) { + uncle = node->parent->parent->right; + if (uncle->color == red) { + node->parent->color = black; + uncle->color = black; + node->parent->parent->color = red; + node = node->parent->parent; + } else /* if (uncle->color == black) */ { + if (node == node->parent->right) { + node = node->parent; + rotate_left(tree, node); + } + node->parent->color = black; + node->parent->parent->color = red; + rotate_right(tree, node->parent->parent); + } + } else { /* if (node->parent == node->parent->parent->right) */ + uncle = node->parent->parent->left; + if (uncle->color == red) { + node->parent->color = black; + uncle->color = black; + node->parent->parent->color = red; + node = node->parent->parent; + } else /* if (uncle->color == black) */ { + if (node == node->parent->left) { + node = node->parent; + rotate_right(tree, node); + } + node->parent->color = black; + node->parent->parent->color = red; + rotate_left(tree, node->parent->parent); + } + } + } + rbfirst(tree)->color = black; /* first node is always black */ + return(NULL); +} + +/* + * Look for a node matching key in tree. + * Returns a pointer to the node if found, else NULL. + */ +struct rbnode * +rbfind(tree, key) + struct rbtree *tree; + void *key; +{ + struct rbnode *node = rbfirst(tree); + int res; + + while (node != rbnil(tree)) { + if ((res = tree->compar(key, node->data)) == 0) + return(node); + node = res < 0 ? node->left : node->right; + } + return(NULL); +} + +/* + * Call func() for each node, passing it the node data and a cookie; + * If func() returns non-zero for a node, the traversal stops and the + * error value is returned. Returns 0 on successful traversal. + */ +int +rbapply_node(tree, node, func, cookie, order) + struct rbtree *tree; + struct rbnode *node; + int (*func)__P((void *, void *)); + void *cookie; + enum rbtraversal order; +{ + int error; + + if (node != rbnil(tree)) { + if (order == preorder) + if ((error = func(node->data, cookie)) != 0) + return(error); + if ((error = rbapply_node(tree, node->left, func, cookie, order)) != 0) + return(error); + if (order == inorder) + if ((error = func(node->data, cookie)) != 0) + return(error); + if ((error = rbapply_node(tree, node->right, func, cookie, order)) != 0) + return(error); + if (order == postorder) + if ((error = func(node->data, cookie)) != 0) + return(error); + } + return (0); +} + +/* + * Returns the successor of node, or nil if there is none. + */ +static struct rbnode * +rbsuccessor(tree, node) + struct rbtree *tree; + struct rbnode *node; +{ + struct rbnode *succ; + + if ((succ = node->right) != rbnil(tree)) { + while (succ->left != rbnil(tree)) + succ = succ->left; + } else { + /* No right child, move up until we find it or hit the root */ + for (succ = node->parent; node == succ->right; succ = succ->parent) + node = succ; + if (succ == rbroot(tree)) + succ = rbnil(tree); + } + return(succ); +} + +/* + * Recursive portion of rbdestroy(). + */ +static void +_rbdestroy(tree, node, destroy) + struct rbtree *tree; + struct rbnode *node; + void (*destroy)__P((void *)); +{ + if (node != rbnil(tree)) { + _rbdestroy(tree, node->left, destroy); + _rbdestroy(tree, node->right, destroy); + if (destroy != NULL) + destroy(node->data); + efree(node); + } +} + +/* + * Destroy the specified tree, calling the destructor destroy + * for each node and then freeing the tree itself. + */ +void +rbdestroy(tree, destroy) + struct rbtree *tree; + void (*destroy)__P((void *)); +{ + _rbdestroy(tree, rbfirst(tree), destroy); + efree(tree); +} + +/* + * Delete node 'z' from the tree and return its data pointer. + */ +void *rbdelete(tree, z) + struct rbtree* tree; + struct rbnode* z; +{ + struct rbnode *x, *y; + void *data = z->data; + + if (z->left == rbnil(tree) || z->right == rbnil(tree)) + y = z; + else + y = rbsuccessor(tree, z); + x = (y->left == rbnil(tree)) ? y->right : y->left; + + if ((x->parent = y->parent) == rbroot(tree)) { + rbfirst(tree) = x; + } else { + if (y == y->parent->left) + y->parent->left = x; + else + y->parent->right = x; + } + if (y->color == black) + rbrepair(tree, x); + if (y != z) { + y->left = z->left; + y->right = z->right; + y->parent = z->parent; + y->color = z->color; + z->left->parent = z->right->parent = y; + if (z == z->parent->left) + z->parent->left = y; + else + z->parent->right = y; + } + free(z); + + return (data); +} + +/* + * Repair the tree after a node has been deleted by rotating and repainting + * colors to restore the 4 properties inherent in red-black trees. + */ +static void +rbrepair(tree, node) + struct rbtree *tree; + struct rbnode *node; +{ + struct rbnode *sibling; + + while (node->color == black) { + if (node == node->parent->left) { + sibling = node->parent->right; + if (sibling->color == red) { + sibling->color = black; + node->parent->color = red; + rotate_left(tree, node->parent); + sibling = node->parent->right; + } + if (sibling->right->color == black && sibling->left->color == black) { + sibling->color = red; + node = node->parent; + } else { + if (sibling->right->color == black) { + sibling->left->color = black; + sibling->color = red; + rotate_right(tree, sibling); + sibling = node->parent->right; + } + sibling->color = node->parent->color; + node->parent->color = black; + sibling->right->color = black; + rotate_left(tree, node->parent); + break; + } + } else { /* if (node == node->parent->right) */ + sibling = node->parent->left; + if (sibling->color == red) { + sibling->color = black; + node->parent->color = red; + rotate_right(tree, node->parent); + sibling = node->parent->left; + } + if (sibling->right->color == black && sibling->left->color == black) { + sibling->color = red; + node = node->parent; + } else { + if (sibling->left->color == black) { + sibling->right->color = black; + sibling->color = red; + rotate_left(tree, sibling); + sibling = node->parent->left; + } + sibling->color = node->parent->color; + node->parent->color = black; + sibling->left->color = black; + rotate_right(tree, node->parent); + break; + } + } + } +} diff --git a/redblack.h b/redblack.h new file mode 100644 index 0000000..8c7ead7 --- /dev/null +++ b/redblack.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004, 2007 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. + * + * $Sudo: redblack.h,v 1.4 2008/11/09 14:13:12 millert Exp $ + */ + +#ifndef _SUDO_REDBLACK_H +#define _SUDO_REDBLACK_H + +enum rbcolor { + red, + black +}; + +enum rbtraversal { + preorder, + inorder, + postorder +}; + +struct rbnode { + struct rbnode *left, *right, *parent; + void *data; + enum rbcolor color; +}; + +struct rbtree { + int (*compar) __P((const void *, const void *)); + struct rbnode root; + struct rbnode nil; +}; + +#define rbapply(t, f, c, o) rbapply_node((t), (t)->root.left, (f), (c), (o)) +#define rbisempty(t) ((t)->root.left == &(t)->nil && (t)->root.right == &(t)->nil) +#define rbfirst(t) ((t)->root.left) +#define rbroot(t) (&(t)->root) +#define rbnil(t) (&(t)->nil) + +void *rbdelete __P((struct rbtree *, struct rbnode *)); +int rbapply_node __P((struct rbtree *, struct rbnode *, + int (*)(void *, void *), void *, + enum rbtraversal)); +struct rbnode *rbfind __P((struct rbtree *, void *)); +struct rbnode *rbinsert __P((struct rbtree *, void *)); +struct rbtree *rbcreate __P((int (*)(const void *, const void *))); +void rbdestroy __P((struct rbtree *, void (*)(void *))); + +#endif /* _SUDO_REDBLACK_H */ diff --git a/sample.pam b/sample.pam index 603fded..b603a84 100644 --- a/sample.pam +++ b/sample.pam @@ -5,7 +5,9 @@ # # There are two basic ways to configure PAM, either via pam_stack # or by explicitly specifying the various methods to use. -# +# +# $Sudo: sample.pam,v 1.3 2004/10/01 14:58:15 millert Exp $ +# # Here we use pam_stack auth required pam_stack.so service=system-auth account required pam_stack.so service=system-auth diff --git a/sample.sudoers b/sample.sudoers index 0682301..220df7f 100644 --- a/sample.sudoers +++ b/sample.sudoers @@ -5,6 +5,17 @@ # # See the sudoers man page for the details on how to write a sudoers file. # +# $Sudo: sample.sudoers,v 1.29 2008/10/03 19:55:57 millert Exp $ + +## +# Override built-in defaults +## +Defaults syslog=auth +Defaults>root !set_logname +Defaults:FULLTIMERS !lecture +Defaults:millert !authenticate +Defaults@SERVERS log_year, logfile=/var/log/sudo.log +Defaults!PAGERS noexec ## # User alias specification @@ -47,15 +58,7 @@ Cmnd_Alias SHELLS = /sbin/sh, /usr/bin/sh, /usr/bin/csh, /usr/bin/ksh, \ Cmnd_Alias SU = /usr/bin/su Cmnd_Alias VIPW = /usr/sbin/vipw, /usr/bin/passwd, /usr/bin/chsh, \ /usr/bin/chfn - -## -# Override built-in defaults -## -Defaults syslog=auth -Defaults>root !set_logname -Defaults:FULLTIMERS !lecture -Defaults:millert !authenticate -Defaults@SERVERS log_year, logfile=/var/log/sudo.log +Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less ## # User specification @@ -85,7 +88,7 @@ operator ALL = DUMPS, KILL, SHUTDOWN, HALT, REBOOT, PRINTING,\ joe ALL = /usr/bin/su operator # pete may change passwords for anyone but root on the hp snakes -pete HPPA = /usr/bin/passwd [A-z]*, !/usr/bin/passwd root +pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root # bob may run anything on the sparc and sgi machines as any user # listed in the Runas_Alias "OP" (ie: root and operator) diff --git a/sample.syslog.conf b/sample.syslog.conf index 2effbab..90e2c61 100644 --- a/sample.syslog.conf +++ b/sample.syslog.conf @@ -16,6 +16,8 @@ # Syslogd will not create new log files for you, you must first # create the file before syslogd will log to it. Eg. # 'touch /var/log/sudo' +# +# $Sudo: sample.syslog.conf,v 1.3 2004/10/01 14:58:15 millert Exp $ # This logs successful and failed sudo attempts to the file /var/log/sudo local2.debug /var/log/sudo diff --git a/schema.ActiveDirectory b/schema.ActiveDirectory new file mode 100644 index 0000000..60f70bc --- /dev/null +++ b/schema.ActiveDirectory @@ -0,0 +1,172 @@ +# +# Active Directory Schema for sudo configuration (sudoers) +# +# To extend your Active Directory schema, run the following command +# on your Windows DC: +# +# ldifde -i -f schema.ActiveDirectory -c dc=X dc=YOURDOMAIN,DC=COM +# + +dn: CN=sudoUser,CN=Schema,CN=Configuration,DC=X +changetype: add +objectClass: top +objectClass: attributeSchema +cn: sudoUser +distinguishedName: CN=sudoUser,CN=Schema,CN=Configuration,DC=X +instanceType: 4 +attributeID: 1.3.6.1.4.1.15953.9.1.1 +attributeSyntax: 2.5.5.5 +isSingleValued: FALSE +showInAdvancedViewOnly: TRUE +adminDisplayName: sudoUser +adminDescription: User(s) who may run sudo +oMSyntax: 22 +searchFlags: 1 +lDAPDisplayName: sudoUser +name: sudoUser +schemaIDGUID:: JrGcaKpnoU+0s+HgeFjAbg== +objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X + +dn: CN=sudoHost,CN=Schema,CN=Configuration,DC=X +changetype: add +objectClass: top +objectClass: attributeSchema +cn: sudoHost +distinguishedName: CN=sudoHost,CN=Schema,CN=Configuration,DC=X +instanceType: 4 +attributeID: 1.3.6.1.4.1.15953.9.1.2 +attributeSyntax: 2.5.5.5 +isSingleValued: FALSE +showInAdvancedViewOnly: TRUE +adminDisplayName: sudoHost +adminDescription: Host(s) who may run sudo +oMSyntax: 22 +lDAPDisplayName: sudoHost +name: sudoHost +schemaIDGUID:: d0TTjg+Y6U28g/Y+ns2k4w== +objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X + +dn: CN=sudoCommand,CN=Schema,CN=Configuration,DC=X +changetype: add +objectClass: top +objectClass: attributeSchema +cn: sudoCommand +distinguishedName: CN=sudoCommand,CN=Schema,CN=Configuration,DC=X +instanceType: 4 +attributeID: 1.3.6.1.4.1.15953.9.1.3 +attributeSyntax: 2.5.5.5 +isSingleValued: FALSE +showInAdvancedViewOnly: TRUE +adminDisplayName: sudoCommand +adminDescription: Command(s) to be executed by sudo +oMSyntax: 22 +lDAPDisplayName: sudoCommand +name: sudoCommand +schemaIDGUID:: D6QR4P5UyUen3RGYJCHCPg== +objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X + +dn: CN=sudoRunAs,CN=Schema,CN=Configuration,DC=X +changetype: add +objectClass: top +objectClass: attributeSchema +cn: sudoRunAs +distinguishedName: CN=sudoRunAs,CN=Schema,CN=Configuration,DC=X +instanceType: 4 +attributeID: 1.3.6.1.4.1.15953.9.1.4 +attributeSyntax: 2.5.5.5 +isSingleValued: FALSE +showInAdvancedViewOnly: TRUE +adminDisplayName: sudoRunAs +adminDescription: User(s) impersonated by sudo (deprecated) +oMSyntax: 22 +lDAPDisplayName: sudoRunAs +name: sudoRunAs +schemaIDGUID:: CP98mCQTyUKKxGrQeM80hQ== +objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X + +dn: CN=sudoOption,CN=Schema,CN=Configuration,DC=X +changetype: add +objectClass: top +objectClass: attributeSchema +cn: sudoOption +distinguishedName: CN=sudoOption,CN=Schema,CN=Configuration,DC=X +instanceType: 4 +attributeID: 1.3.6.1.4.1.15953.9.1.5 +attributeSyntax: 2.5.5.5 +isSingleValued: FALSE +showInAdvancedViewOnly: TRUE +adminDisplayName: sudoOption +adminDescription: Option(s) followed by sudo +oMSyntax: 22 +lDAPDisplayName: sudoOption +name: sudoOption +schemaIDGUID:: ojaPzBBlAEmsvrHxQctLnA== +objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X + +dn: CN=sudoRunAsUser,CN=Schema,CN=Configuration,DC=X +changetype: add +objectClass: top +objectClass: attributeSchema +cn: sudoRunAsUser +distinguishedName: CN=sudoRunAsUser,CN=Schema,CN=Configuration,DC=X +instanceType: 4 +attributeID: 1.3.6.1.4.1.15953.9.1.6 +attributeSyntax: 2.5.5.5 +isSingleValued: FALSE +showInAdvancedViewOnly: TRUE +adminDisplayName: sudoRunAsUser +adminDescription: User(s) impersonated by sudo +oMSyntax: 22 +lDAPDisplayName: sudoRunAsUser +name: sudoRunAsUser +schemaIDGUID:: 9C52yPYd3RG3jMR2VtiVkw== +objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X + +dn: CN=sudoRunAsGroup,CN=Schema,CN=Configuration,DC=X +changetype: add +objectClass: top +objectClass: attributeSchema +cn: sudoRunAsGroup +distinguishedName: CN=sudoRunAsGroup,CN=Schema,CN=Configuration,DC=X +instanceType: 4 +attributeID: 1.3.6.1.4.1.15953.9.1.7 +attributeSyntax: 2.5.5.5 +isSingleValued: FALSE +showInAdvancedViewOnly: TRUE +adminDisplayName: sudoRunAsGroup +adminDescription: Groups(s) impersonated by sudo +oMSyntax: 22 +lDAPDisplayName: sudoRunAsGroup +name: sudoRunAsGroup +schemaIDGUID:: xJhSt/Yd3RGJPTB1VtiVkw== +objectCategory: CN=Attribute-Schema,CN=Schema,CN=Configuration,DC=X + +dn: CN=sudoRole,CN=Schema,CN=Configuration,DC=X +changetype: add +objectClass: top +objectClass: classSchema +cn: sudoRole +distinguishedName: CN=sudoRole,CN=Schema,CN=Configuration,DC=X +instanceType: 4 +possSuperiors: container +possSuperiors: top +subClassOf: top +governsID: 1.3.6.1.4.1.15953.9.2.1 +mayContain: sudoCommand +mayContain: sudoHost +mayContain: sudoOption +mayContain: sudoRunAs +mayContain: sudoRunAsUser +mayContain: sudoRunAsGroup +mayContain: sudoUser +rDNAttID: cn +showInAdvancedViewOnly: FALSE +adminDisplayName: sudoRole +adminDescription: Sudoer Entries +objectClassCategory: 1 +lDAPDisplayName: sudoRole +name: sudoRole +schemaIDGUID:: SQn432lnZ0+ukbdh3+gN3w== +systemOnly: FALSE +objectCategory: CN=Class-Schema,CN=Schema,CN=Configuration,DC=X +defaultObjectCategory: CN=sudoRole,CN=Schema,CN=Configuration,DC=X diff --git a/schema.OpenLDAP b/schema.OpenLDAP index 3e2e655..df3fc0f 100644 --- a/schema.OpenLDAP +++ b/schema.OpenLDAP @@ -25,7 +25,7 @@ attributetype ( 1.3.6.1.4.1.15953.9.1.3 attributetype ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' - DESC 'User(s) impersonated by sudo' + DESC 'User(s) impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) @@ -35,9 +35,21 @@ attributetype ( 1.3.6.1.4.1.15953.9.1.5 EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +attributetype ( 1.3.6.1.4.1.15953.9.1.6 + NAME 'sudoRunAsUser' + DESC 'User(s) impersonated by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +attributetype ( 1.3.6.1.4.1.15953.9.1.7 + NAME 'sudoRunAsGroup' + DESC 'Group(s) impersonated by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL DESC 'Sudoer Entries' MUST ( cn ) - MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoOption $ + MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ description ) ) diff --git a/schema.iPlanet b/schema.iPlanet index 879c2e9..3718fd7 100644 --- a/schema.iPlanet +++ b/schema.iPlanet @@ -2,6 +2,8 @@ dn: cn=schema attributeTypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser' DESC 'User(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' ) attributeTypes: ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' ) attributeTypes: ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand' DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' ) -attributeTypes: ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' ) +attributeTypes: ( 1.3.6.1.4.1.15953.9.1.4 NAME 'sudoRunAs' DESC 'User(s) impersonated by sudo (deprecated)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' ) attributeTypes: ( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption' DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' ) -objectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL DESC 'Sudoer Entries' MUST ( cn ) MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoOption $ description ) X-ORIGIN 'SUDO' ) +attributeTypes: ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser' DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' ) +attributeTypes: ( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup' DESC 'Group(s) impersonated by sudo' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'SUDO' ) +objectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL DESC 'Sudoer Entries' MUST ( cn ) MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ description ) X-ORIGIN 'SUDO' ) diff --git a/selinux.c b/selinux.c index 7d49854..05ac1a0 100644 --- a/selinux.c +++ b/selinux.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -50,7 +49,7 @@ #include "pathnames.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: selinux.c,v 1.2.2.4 2008/02/22 20:33:10 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: selinux.c,v 1.5 2008/02/22 20:33:00 millert Exp $"; #endif /* lint */ /* @@ -77,17 +76,17 @@ restore_tty_label(int fd, const char *ttyn, security_context_t tty_context, /* Verify that the tty still has the context set by sudo. */ if ((rc = fgetfilecon(fd, &chk_tty_context)) < 0) { - warn("unable to fgetfilecon %s", ttyn); + warning("unable to fgetfilecon %s", ttyn); goto skip_relabel; } if ((rc = strcmp(chk_tty_context, new_tty_context))) { - warnx("%s changed labels.", ttyn); + warningx("%s changed labels.", ttyn); goto skip_relabel; } if ((rc = fsetfilecon(fd, tty_context)) < 0) - warn("unable to restore context for %s", ttyn); + warning("unable to restore context for %s", ttyn); skip_relabel: freecon(chk_tty_context); @@ -117,13 +116,13 @@ relabel_tty(const char *ttyn, security_context_t new_context, /* Re-open TTY descriptor */ fd = open(ttyn, O_RDWR | O_NONBLOCK); if (fd == -1) { - warn("unable to open %s", ttyn); + warning("unable to open %s", ttyn); return(-1); } (void)fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); if (fgetfilecon(fd, &tty_con) < 0) { - warn("unable to get current context for %s, not relabeling tty", + warning("unable to get current context for %s, not relabeling tty", ttyn); if (enforcing) goto error; @@ -131,14 +130,14 @@ relabel_tty(const char *ttyn, security_context_t new_context, if (tty_con && (security_compute_relabel(new_context, tty_con, SECCLASS_CHR_FILE, &new_tty_con) < 0)) { - warn("unable to get new context for %s, not relabeling tty", ttyn); + warning("unable to get new context for %s, not relabeling tty", ttyn); if (enforcing) goto error; } if (new_tty_con != NULL) { if (fsetfilecon(fd, new_tty_con) < 0) { - warn("unable to set new context for %s", ttyn); + warning("unable to set new context for %s", ttyn); if (enforcing) goto error; } @@ -167,12 +166,12 @@ get_exec_context(security_context_t old_context, char *role, char *type) /* We must have a role, the type is optional (we can use the default). */ if (!role) { - warnx("you must specify a role."); + warningx("you must specify a role."); return(NULL); } if (!type) { if (get_default_type(role, &typebuf)) { - warnx("unable to get default type"); + warningx("unable to get default type"); return(NULL); } type = typebuf; @@ -189,11 +188,11 @@ get_exec_context(security_context_t old_context, char *role, char *type) * type we will be running the command as. */ if (context_role_set(context, role)) { - warnx("failed to set new role %s", role); + warningx("failed to set new role %s", role); goto error; } if (context_type_set(context, type)) { - warnx("failed to set new type %s", type); + warningx("failed to set new type %s", type); goto error; } @@ -202,12 +201,12 @@ get_exec_context(security_context_t old_context, char *role, char *type) */ new_context = estrdup(context_str(context)); if (security_check_context(new_context) < 0) { - warnx("%s is not a valid context", new_context); + warningx("%s is not a valid context", new_context); goto error; } #ifdef DEBUG - warnx("Your new context is %s", new_context); + warningx("Your new context is %s", new_context); #endif context_free(context); @@ -227,7 +226,7 @@ error: * will simply execute the command pass to it on the command line. */ void -selinux_exec(char *role, char *type, char **argv, char **envp, int login_shell) +selinux_exec(char *role, char *type, char **argv, int login_shell) { security_context_t old_context = NULL; security_context_t new_context = NULL; @@ -238,19 +237,19 @@ selinux_exec(char *role, char *type, char **argv, char **envp, int login_shell) /* Must have a tty. */ if (user_ttypath == NULL || *user_ttypath == '\0') - err(EXIT_FAILURE, "unable to determine tty"); + error(EXIT_FAILURE, "unable to determine tty"); /* Store the caller's SID in old_context. */ if (getprevcon(&old_context)) - err(EXIT_FAILURE, "failed to get old_context"); + error(EXIT_FAILURE, "failed to get old_context"); enforcing = security_getenforce(); if (enforcing < 0) - err(EXIT_FAILURE, "unable to determine enforcing mode."); + error(EXIT_FAILURE, "unable to determine enforcing mode."); #ifdef DEBUG - warnx("your old context was %s", old_context); + warningx("your old context was %s", old_context); #endif new_context = get_exec_context(old_context, role, type); if (!new_context) @@ -259,19 +258,19 @@ selinux_exec(char *role, char *type, char **argv, char **envp, int login_shell) ttyfd = relabel_tty(user_ttypath, new_context, &tty_context, &new_tty_context, enforcing); if (ttyfd < 0) - err(EXIT_FAILURE, "unable to setup tty context for %s", new_context); + error(EXIT_FAILURE, "unable to setup tty context for %s", new_context); #ifdef DEBUG - warnx("your old tty context is %s", tty_context); - warnx("your new tty context is %s", new_tty_context); + warningx("your old tty context is %s", tty_context); + warningx("your new tty context is %s", new_tty_context); #endif childPid = fork(); if (childPid < 0) { /* fork failed, no child to worry about */ - warn("unable to fork"); + warning("unable to fork"); if (restore_tty_label(ttyfd, user_ttypath, tty_context, new_tty_context)) - warnx("unable to restore tty label"); + warningx("unable to restore tty label"); exit(EXIT_FAILURE); } else if (childPid) { pid_t pid; @@ -283,10 +282,10 @@ selinux_exec(char *role, char *type, char **argv, char **envp, int login_shell) } while (pid == -1 && errno == EINTR); if (pid == -1) - err(EXIT_FAILURE, "waitpid"); + error(EXIT_FAILURE, "waitpid"); if (restore_tty_label(ttyfd, user_ttypath, tty_context, new_tty_context)) - errx(EXIT_FAILURE, "unable to restore tty label"); + errorx(EXIT_FAILURE, "unable to restore tty label"); /* Preserve child exit status. */ if (WIFEXITED(status)) @@ -297,7 +296,7 @@ selinux_exec(char *role, char *type, char **argv, char **envp, int login_shell) /* Close the tty and reopen descriptors 0 through 2 */ if (close(ttyfd) || close(STDIN_FILENO) || close(STDOUT_FILENO) || close(STDERR_FILENO)) { - warn("could not close descriptors"); + warning("could not close descriptors"); goto error; } ttyfd = open(user_ttypath, O_RDONLY | O_NONBLOCK); @@ -313,13 +312,13 @@ selinux_exec(char *role, char *type, char **argv, char **envp, int login_shell) goto error; if (setexeccon(new_context)) { - warn("unable to set exec context to %s", new_context); + warning("unable to set exec context to %s", new_context); if (enforcing) goto error; } if (setkeycreatecon(new_context)) { - warn("unable to set key creation context to %s", new_context); + warning("unable to set key creation context to %s", new_context); if (enforcing) goto error; } @@ -334,8 +333,8 @@ selinux_exec(char *role, char *type, char **argv, char **envp, int login_shell) argv[0] = login_shell ? "-sesh" : "sesh"; argv[1] = safe_cmnd; - execve(_PATH_SUDO_SESH, argv, envp); - warn("%s", safe_cmnd); + execv(_PATH_SUDO_SESH, argv); + warning("%s", safe_cmnd); error: _exit(EXIT_FAILURE); diff --git a/sesh.c b/sesh.c index 06728d4..715980e 100644 --- a/sesh.c +++ b/sesh.c @@ -30,7 +30,7 @@ #include "compat.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: sesh.c,v 1.1.2.1 2008/02/09 14:44:49 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: sesh.c,v 1.1 2008/02/09 14:30:06 millert Exp $"; #endif /* lint */ int diff --git a/set_perms.c b/set_perms.c index 77c68e9..bc88a84 100644 --- a/set_perms.c +++ b/set_perms.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994-1996,1998-2006 Todd C. Miller + * Copyright (c) 1994-1996,1998-2008 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 @@ -42,11 +42,6 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #include #include @@ -57,7 +52,7 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: set_perms.c,v 1.30.2.7 2007/11/27 23:41:23 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: set_perms.c,v 1.44 2008/03/06 17:19:56 millert Exp $"; #endif /* lint */ #ifdef __TANDEM @@ -86,13 +81,17 @@ void set_perms(perm) int perm; { + const char *errstr; + if (perm == current_perm) return; switch (perm) { case PERM_ROOT: - if (setresuid(ROOT_UID, ROOT_UID, ROOT_UID)) - errx(1, "setresuid(ROOT_UID, ROOT_UID, ROOT_UID) failed, your operating system may have a broken setresuid() function\nTry running configure with --disable-setresuid"); + if (setresuid(ROOT_UID, ROOT_UID, ROOT_UID)) { + errstr = "setresuid(ROOT_UID, ROOT_UID, ROOT_UID)"; + goto bad; + } (void) setresgid(-1, user_gid, -1); if (current_perm == PERM_RUNAS) restore_groups(); @@ -100,22 +99,30 @@ set_perms(perm) case PERM_USER: (void) setresgid(-1, user_gid, -1); - if (setresuid(user_uid, user_uid, ROOT_UID)) - err(1, "setresuid(user_uid, user_uid, ROOT_UID)"); + if (setresuid(user_uid, user_uid, ROOT_UID)) { + errstr = "setresuid(user_uid, user_uid, ROOT_UID)"; + goto bad; + } break; case PERM_FULL_USER: /* headed for exec() */ (void) setgid(user_gid); - if (setresuid(user_uid, user_uid, user_uid)) - err(1, "setresuid(user_uid, user_uid, user_uid)"); + if (setresuid(user_uid, user_uid, user_uid)) { + errstr = "setresuid(user_uid, user_uid, user_uid)"; + goto bad; + } break; case PERM_RUNAS: runas_setgroups(); - (void) setresgid(-1, runas_pw->pw_gid, -1); - if (setresuid(-1, runas_pw->pw_uid, -1)) - err(1, "unable to change to runas uid"); + (void) setresgid(-1, runas_gr ? + runas_gr->gr_gid : runas_pw->pw_gid, -1); + if (setresuid(-1, runas_pw ? runas_pw->pw_uid : + user_uid, -1)) { + errstr = "unable to change to runas uid"; + goto bad; + } break; case PERM_FULL_RUNAS: @@ -123,14 +130,16 @@ set_perms(perm) runas_setup(); if (setresuid(def_stay_setuid ? user_uid : runas_pw->pw_uid, - runas_pw->pw_uid, runas_pw->pw_uid)) - err(1, "unable to change to runas uid"); + runas_pw->pw_uid, runas_pw->pw_uid)) { + errstr = "unable to change to runas uid"; + goto bad; + } break; case PERM_SUDOERS: /* assume euid == ROOT_UID, ruid == user */ if (setresgid(-1, SUDOERS_GID, -1)) - err(1, "unable to change to sudoers gid"); + error(1, "unable to change to sudoers gid"); /* * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE @@ -140,20 +149,30 @@ set_perms(perm) * work on all OS's. */ if (SUDOERS_UID == ROOT_UID) { - if ((SUDOERS_MODE & 040) && setresuid(ROOT_UID, 1, ROOT_UID)) - err(1, "setresuid(ROOT_UID, 1, ROOT_UID)"); + if ((SUDOERS_MODE & 040) && setresuid(ROOT_UID, 1, ROOT_UID)) { + errstr = "setresuid(ROOT_UID, 1, ROOT_UID)"; + goto bad; + } } else { - if (setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)) - err(1, "setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)"); + if (setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)) { + errstr = "setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)"; + goto bad; + } } break; case PERM_TIMESTAMP: - if (setresuid(ROOT_UID, timestamp_uid, ROOT_UID)) - err(1, "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)"); + if (setresuid(ROOT_UID, timestamp_uid, ROOT_UID)) { + errstr = "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)"; + goto bad; + } break; } current_perm = perm; + return; +bad: + errorx(1, "%s: %s", errstr, + errno == EAGAIN ? "too many processes" : strerror(errno)); } #else @@ -169,15 +188,21 @@ void set_perms(perm) int perm; { + const char *errstr; + if (perm == current_perm) return; switch (perm) { case PERM_ROOT: - if (setreuid(-1, ROOT_UID)) - errx(1, "setreuid(-1, ROOT_UID) failed, your operating system may have a broken setreuid() function\nTry running configure with --disable-setreuid"); - if (setuid(ROOT_UID)) - err(1, "setuid(ROOT_UID)"); + if (setreuid(-1, ROOT_UID)) { + errstr = "setreuid(-1, ROOT_UID)"; + goto bad; + } + if (setuid(ROOT_UID)) { + errstr = "setuid(ROOT_UID)"; + goto bad; + } (void) setregid(-1, user_gid); if (current_perm == PERM_RUNAS) restore_groups(); @@ -185,36 +210,46 @@ set_perms(perm) case PERM_USER: (void) setregid(-1, user_gid); - if (setreuid(ROOT_UID, user_uid)) - err(1, "setreuid(ROOT_UID, user_uid)"); + if (setreuid(ROOT_UID, user_uid)) { + errstr = "setreuid(ROOT_UID, user_uid)"; + goto bad; + } break; case PERM_FULL_USER: /* headed for exec() */ (void) setgid(user_gid); - if (setreuid(user_uid, user_uid)) - err(1, "setreuid(user_uid, user_uid)"); + if (setreuid(user_uid, user_uid)) { + errstr = "setreuid(user_uid, user_uid)"; + goto bad; + } break; case PERM_RUNAS: runas_setgroups(); - (void) setregid(-1, runas_pw->pw_gid); - if (setreuid(-1, runas_pw->pw_uid)) - err(1, "unable to change to runas uid"); + (void) setregid(-1, runas_gr ? + runas_gr->gr_gid : runas_pw->pw_gid); + if (setreuid(-1, + runas_pw ? runas_pw->pw_uid : user_uid)) { + errstr = "unable to change to runas uid"; + goto bad; + } break; case PERM_FULL_RUNAS: /* headed for exec(), assume euid == ROOT_UID */ runas_setup(); if (setreuid(def_stay_setuid ? user_uid : - runas_pw->pw_uid, runas_pw->pw_uid)) - err(1, "unable to change to runas uid"); + runas_pw->pw_uid, runas_pw->pw_uid)) { + errstr = "unable to change to runas uid"; + goto bad; + } break; case PERM_SUDOERS: /* assume euid == ROOT_UID, ruid == user */ if (setregid(-1, SUDOERS_GID)) - err(1, "unable to change to sudoers gid"); + error(1, "unable to change to sudoers gid"); /* * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE @@ -224,20 +259,30 @@ set_perms(perm) * work on all OS's. */ if (SUDOERS_UID == ROOT_UID) { - if ((SUDOERS_MODE & 040) && setreuid(ROOT_UID, 1)) - err(1, "setreuid(ROOT_UID, 1)"); + if ((SUDOERS_MODE & 040) && setreuid(ROOT_UID, 1)) { + errstr = "setreuid(ROOT_UID, 1)"; + goto bad; + } } else { - if (setreuid(ROOT_UID, SUDOERS_UID)) - err(1, "setreuid(ROOT_UID, SUDOERS_UID)"); + if (setreuid(ROOT_UID, SUDOERS_UID)) { + errstr = "setreuid(ROOT_UID, SUDOERS_UID)"; + goto bad; + } } break; case PERM_TIMESTAMP: - if (setreuid(ROOT_UID, timestamp_uid)) - err(1, "setreuid(ROOT_UID, timestamp_uid)"); + if (setreuid(ROOT_UID, timestamp_uid)) { + errstr = "setreuid(ROOT_UID, timestamp_uid)"; + goto bad; + } break; } current_perm = perm; + return; +bad: + errorx(1, "%s: %s", errstr, + errno == EAGAIN ? "too many processes" : strerror(errno)); } # else /* !HAVE_SETRESUID && !HAVE_SETREUID */ @@ -251,6 +296,8 @@ void set_perms(perm) int perm; { + const char *errstr; + if (perm == current_perm) return; @@ -259,10 +306,14 @@ set_perms(perm) * for these calls differ on various systems, we set * real and effective uids to ROOT_UID initially to be safe. */ - if (seteuid(ROOT_UID)) - err(1, "seteuid(ROOT_UID)"); - if (setuid(ROOT_UID)) - err(1, "setuid(ROOT_UID)"); + if (seteuid(ROOT_UID)) { + errstr = "seteuid(ROOT_UID)"; + goto bad; + } + if (setuid(ROOT_UID)) { + errstr = "setuid(ROOT_UID)"; + goto bad; + } switch (perm) { case PERM_ROOT: @@ -274,34 +325,43 @@ set_perms(perm) case PERM_USER: (void) setegid(user_gid); - if (seteuid(user_uid)) - err(1, "seteuid(user_uid)"); + if (seteuid(user_uid)) { + errstr = "seteuid(user_uid)"; + goto bad; + } break; case PERM_FULL_USER: /* headed for exec() */ (void) setgid(user_gid); - if (setuid(user_uid)) - err(1, "setuid(user_uid)"); + if (setuid(user_uid)) { + errstr = "setuid(user_uid)"; + goto bad; + } break; case PERM_RUNAS: runas_setgroups(); - (void) setegid(runas_pw->pw_gid); - if (seteuid(runas_pw->pw_uid)) - err(1, "unable to change to runas uid"); + (void) setegid(runas_gr ? + runas_gr->gr_gid : runas_pw->pw_gid); + if (seteuid(runas_pw ? runas_pw->pw_uid : user_uid)) { + errstr = "unable to change to runas uid"; + goto bad; + } break; case PERM_FULL_RUNAS: /* headed for exec() */ runas_setup(); - if (setuid(runas_pw->pw_uid)) - err(1, "unable to change to runas uid"); + if (setuid(runas_pw->pw_uid)) { + errstr = "unable to change to runas uid"; + goto bad; + } break; case PERM_SUDOERS: if (setegid(SUDOERS_GID)) - err(1, "unable to change to sudoers gid"); + error(1, "unable to change to sudoers gid"); /* * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE @@ -311,20 +371,30 @@ set_perms(perm) * work on all OS's. */ if (SUDOERS_UID == ROOT_UID) { - if ((SUDOERS_MODE & 040) && seteuid(1)) - err(1, "seteuid(1)"); + if ((SUDOERS_MODE & 040) && seteuid(1)) { + errstr = "seteuid(1)"; + goto bad; + } } else { - if (seteuid(SUDOERS_UID)) - err(1, "seteuid(SUDOERS_UID)"); + if (seteuid(SUDOERS_UID)) { + errstr = "seteuid(SUDOERS_UID)"; + goto bad; + } } break; case PERM_TIMESTAMP: - if (seteuid(timestamp_uid)) - err(1, "seteuid(timestamp_uid)"); + if (seteuid(timestamp_uid)) { + errstr = "seteuid(timestamp_uid)"; + goto bad; + } break; } current_perm = perm; + return; +bad: + errorx(1, "%s: %s", errstr, + errno == EAGAIN ? "too many processes" : strerror(errno)); } # else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */ @@ -338,27 +408,35 @@ void set_perms(perm) int perm; { + const char *errstr; + if (perm == current_perm) return; switch (perm) { case PERM_ROOT: - if (setuid(ROOT_UID)) - err(1, "setuid(ROOT_UID)"); + if (setuid(ROOT_UID)) { + errstr = "setuid(ROOT_UID)"; + goto bad; + } if (current_perm == PERM_RUNAS) restore_groups(); break; case PERM_FULL_USER: (void) setgid(user_gid); - if (setuid(user_uid)) - err(1, "setuid(user_uid)"); + if (setuid(user_uid)) { + errstr = "setuid(user_uid)"; + goto bad; + } break; case PERM_FULL_RUNAS: runas_setup(); - if (setuid(runas_pw->pw_uid)) - err(1, "unable to change to runas uid"); + if (setuid(runas_pw->pw_uid)) { + errstr = "unable to change to runas uid"; + goto bad; + } break; case PERM_USER: @@ -370,6 +448,10 @@ set_perms(perm) } current_perm = perm; + return; +bad: + errorx(1, "%s: %s", errstr, + errno == EAGAIN ? "too many processes" : strerror(errno)); } # endif /* HAVE_SETEUID */ # endif /* HAVE_SETREUID */ @@ -430,12 +512,17 @@ restore_groups() static void runas_setup() { + gid_t gid; #ifdef HAVE_LOGIN_CAP_H int flags; extern login_cap_t *lc; #endif if (runas_pw->pw_name != NULL) { + gid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid; +#ifdef HAVE_GETUSERATTR + aix_setlimits(runas_pw->pw_name); +#endif #ifdef HAVE_PAM pam_prep_user(runas_pw); #endif /* HAVE_PAM */ @@ -448,20 +535,20 @@ runas_setup() flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY; if (!def_preserve_groups) SET(flags, LOGIN_SETGROUP); - else if (setgid(runas_pw->pw_gid)) - warn("cannot set gid to runas gid"); + 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) - err(1, "unable to set user context"); + error(1, "unable to set user context"); else - warn("unable to set user context"); + warning("unable to set user context"); } } #endif /* HAVE_LOGIN_CAP_H */ - if (setgid(runas_pw->pw_gid)) - warn("cannot set gid to runas gid"); + if (setgid(gid)) + warning("cannot set gid to runas gid"); /* - * Initialize group vector unless asked not to. + * Initialize group vector */ runas_setgroups(); } diff --git a/sigaction.c b/sigaction.c index d334ebf..3af91c5 100644 --- a/sigaction.c +++ b/sigaction.c @@ -24,7 +24,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: sigaction.c,v 1.5.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: sigaction.c,v 1.7 2005/02/12 22:56:06 millert Exp $"; #endif /* lint */ int diff --git a/snprintf.c b/snprintf.c index 4b7b2b5..e9410c0 100644 --- a/snprintf.c +++ b/snprintf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2008 Todd C. Miller * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * @@ -52,6 +52,9 @@ # include # endif #endif /* STDC_HEADERS */ +#ifdef HAVE_STDINT_H +# include +#endif #ifdef HAVE_STRING_H # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) # include @@ -76,7 +79,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: snprintf.c,v 1.14.4.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: snprintf.c,v 1.22 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ static int xxxprintf __P((char **, size_t, int, const char *, va_list)); @@ -91,18 +94,18 @@ static int xxxprintf __P((char **, size_t, int, const char *, va_list)); # define LONG_MAX (ULONG_MAX / 2) #endif #ifdef HAVE_LONG_LONG -# ifndef UQUAD_MAX -# ifdef ULONG_LONG_MAX -# define UQUAD_MAX ULONG_LONG_MAX +# ifndef ULLONG_MAX +# ifdef UQUAD_MAX +# define ULLONG_MAX UQUAD_MAX # else -# define UQUAD_MAX ((unsigned long long)-1) +# define ULLONG_MAX ((unsigned long long)-1) # endif # endif -# ifndef QUAD_MAX -# ifdef LONG_LONG_MAX -# define QUAD_MAX LONG_LONG_MAX +# ifndef LLONG_MAX +# ifdef QUAD_MAX +# define LLONG_MAX QUAD_MAX # else -# define QUAD_MAX (UQUAD_MAX / 2) +# define LLONG_MAX (ULLONG_MAX / 2) # endif # endif #endif /* HAVE_LONG_LONG */ @@ -129,9 +132,9 @@ static int xxxprintf __P((char **, size_t, int, const char *, va_list)); #define BUF 68 #ifndef HAVE_MEMCHR -VOID * +void * memchr(s, c, n) - const VOID *s; + const void *s; unsigned char c; size_t n; { @@ -140,7 +143,7 @@ memchr(s, c, n) do { if (*p++ == c) - return ((VOID *)(p - 1)); + return ((void *)(p - 1)); } while (--n != 0); } return (NULL); @@ -237,7 +240,7 @@ __uqtoa(val, endp, base, octzero, xdigs) *--cp = to_char(val % 10); return (cp); } - if (val > QUAD_MAX) { + if (val > LLONG_MAX) { *--cp = to_char(val % 10); sval = val / 10; } else @@ -537,7 +540,7 @@ reswitch: switch (ch) { * defined manner.'' * -- ANSI X3J11 */ - ulval = (unsigned long)va_arg(ap, VOID *); + ulval = (unsigned long)va_arg(ap, void *); base = 16; xdigs = "0123456789abcdef"; flags = (flags & ~QUADINT) | HEXPREFIX; diff --git a/strcasecmp.c b/strcasecmp.c index a21e805..fa47bd3 100644 --- a/strcasecmp.c +++ b/strcasecmp.c @@ -19,7 +19,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: strcasecmp.c,v 1.3.4.2 2007/06/12 16:19:15 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: strcasecmp.c,v 1.7 2005/02/12 22:56:06 millert Exp $"; #endif /* lint */ /* diff --git a/strerror.c b/strerror.c index 7a50245..1e0267c 100644 --- a/strerror.c +++ b/strerror.c @@ -25,7 +25,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: strerror.c,v 1.8.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: strerror.c,v 1.11 2005/02/12 22:56:06 millert Exp $"; #endif /* lint */ /* diff --git a/strlcat.c b/strlcat.c index fefe57b..2084bdd 100644 --- a/strlcat.c +++ b/strlcat.c @@ -23,7 +23,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: strlcat.c,v 1.4.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: strlcat.c,v 1.7 2005/02/12 22:56:06 millert Exp $"; #endif /* lint */ diff --git a/strlcpy.c b/strlcpy.c index d7883c0..b03316d 100644 --- a/strlcpy.c +++ b/strlcpy.c @@ -22,7 +22,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: strlcpy.c,v 1.4.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: strlcpy.c,v 1.7 2005/02/12 22:56:06 millert Exp $"; #endif /* lint */ /* diff --git a/sudo.c b/sudo.c index 7348fcf..7191ee1 100644 --- a/sudo.c +++ b/sudo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1993-1996,1998-2007 Todd C. Miller + * Copyright (c) 1993-1996, 1998-2008 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 @@ -59,11 +59,6 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #include #include @@ -101,36 +96,36 @@ #endif #include "sudo.h" +#include "sudo_usage.h" +#include "lbuf.h" #include "interfaces.h" #include "version.h" #ifndef lint -__unused __unused static const char rcsid[] = "$Sudo: sudo.c,v 1.369.2.41 2008/06/21 19:04:07 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: sudo.c,v 1.500 2008/11/18 15:57:09 millert Exp $"; #endif /* lint */ /* * Prototypes */ -static int init_vars __P((int, char **)); +static void init_vars __P((int, char **)); +static int set_cmnd __P((int)); static int parse_args __P((int, char **)); -static void check_sudoers __P((void)); static void initial_setup __P((void)); static void set_loginclass __P((struct passwd *)); static void set_project __P((struct passwd *)); +static void set_runasgr __P((char *)); +static void set_runaspw __P((char *)); +static void show_version __P((void)); static void usage __P((int)) __attribute__((__noreturn__)); static void usage_excl __P((int)) __attribute__((__noreturn__)); -static void usage_excl __P((int)); static struct passwd *get_authpw __P((void)); extern int sudo_edit __P((int, char **, char **)); -extern void list_matches __P((void)); -extern char **rebuild_env __P((char **, int, int)); -extern void validate_env_vars __P((struct list_member *)); -extern char **insert_env_vars __P((char **, struct list_member *)); -extern struct passwd *sudo_getpwnam __P((const char *)); -extern struct passwd *sudo_getpwuid __P((uid_t)); -extern struct passwd *sudo_pwdup __P((const struct passwd *)); +extern void rebuild_env __P((int, int)); +void validate_env_vars __P((struct list_member *)); +void insert_env_vars __P((struct list_member *)); /* * Globals @@ -138,14 +133,17 @@ extern struct passwd *sudo_pwdup __P((const struct passwd *)); int Argc, NewArgc; char **Argv, **NewArgv; char *prev_user; +static int user_closefrom = -1; struct sudo_user sudo_user; -struct passwd *auth_pw; -FILE *sudoers_fp; +struct passwd *auth_pw, *list_pw; struct interface *interfaces; int num_interfaces; int tgetpass_flags; +int long_list; uid_t timestamp_uid; extern int errorlineno; +extern int parse_error; +extern char *errorfile; #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) static struct rlimit corelimit; #endif /* RLIMIT_CORE && !SUDO_DEVEL */ @@ -156,7 +154,13 @@ login_cap_t *lc; char *login_style; #endif /* HAVE_BSD_AUTH_H */ sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp; +static char *runas_user; +static char *runas_group; +static struct sudo_nss_list *snl; +/* For getopt(3) */ +extern char *optarg; +extern int optind; int main(argc, argv, envp) @@ -164,14 +168,14 @@ main(argc, argv, envp) char **argv; char **envp; { - int validated; - int fd; - int cmnd_status; - int sudo_mode; - int pwflag; + int sources = 0, validated; + int fd, cmnd_status, sudo_mode, pwflag, rc = 0; sigaction_t sa; - extern int printmatches; - extern char **environ; + struct sudo_nss *nss; +#if defined(SUDO_DEVEL) && defined(__OpenBSD__) + extern char *malloc_options; + malloc_options = "AFGJPR"; +#endif #ifdef HAVE_SETLOCALE setlocale(LC_ALL, ""); @@ -190,7 +194,7 @@ main(argc, argv, envp) #endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */ if (geteuid() != 0) - errx(1, "must be setuid root"); + errorx(1, "must be setuid root"); /* * Signal setup: @@ -198,6 +202,7 @@ main(argc, argv, envp) * us at some point and avoid the logging. * Install handler to wait for children when they exit. */ + zero_bytes(&sa, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = SIG_IGN; @@ -206,10 +211,11 @@ main(argc, argv, envp) (void) sigaction(SIGTSTP, &sa, &saved_sa_tstp); /* - * Turn off core dumps and close open files. + * Turn off core dumps and make sure fds 0-2 are open. */ initial_setup(); - setpwent(); + sudo_setpwent(); + sudo_setgrent(); /* Parse our arguments. */ sudo_mode = parse_args(Argc, Argv); @@ -228,15 +234,7 @@ main(argc, argv, envp) else switch (sudo_mode) { case MODE_VERSION: - (void) printf("Sudo version %s\n", version); - if (getuid() == 0) { - putchar('\n'); - (void) printf("Sudoers path: %s\n", _PATH_SUDOERS); - dump_auth_methods(); - dump_defaults(); - dump_interfaces(); - } - exit(0); + show_version(); break; case MODE_HELP: usage(0); @@ -257,7 +255,9 @@ main(argc, argv, envp) case MODE_LIST: user_cmnd = "list"; pwflag = I_LISTPW; - printmatches = 1; + break; + case MODE_CHECK: + pwflag = I_LISTPW; break; } @@ -265,31 +265,97 @@ main(argc, argv, envp) if (user_cmnd == NULL && NewArgc == 0) usage(1); - cmnd_status = init_vars(sudo_mode, environ); + init_vars(sudo_mode, envp); /* XXX - move this later? */ -#ifdef HAVE_LDAP - validated = sudo_ldap_check(pwflag); + /* Parse nsswitch.conf for sudoers order. */ + snl = sudo_read_nss(); + + /* Open and parse sudoers, set global defaults */ + tq_foreach_fwd(snl, nss) { + if (nss->open(nss) == 0 && nss->parse(nss) == 0) { + sources++; + nss->setdefs(nss); + } + } + if (sources == 0) + log_error(0, "no valid sudoers sources found, quitting"); + + /* XXX - collect post-sudoers parse settings into a function */ + + /* + * Set runas passwd/group entries based on command line or sudoers. + * Note that if runas_group was specified without runas_user we + * defer setting runas_pw so the match routines know to ignore it. + */ + if (runas_group != NULL) { + set_runasgr(runas_group); + if (runas_user != NULL) + set_runaspw(runas_user); + } else + set_runaspw(runas_user ? runas_user : def_runas_default); + + if (!update_defaults(SETDEF_RUNAS)) + log_error(NO_STDERR|NO_EXIT, "problem with defaults entries"); - /* Skip reading /etc/sudoers if LDAP told us to */ - if (!def_ignore_local_sudoers) { - int v; + /* Set login class if applicable. */ + set_loginclass(sudo_user.pw); - check_sudoers(); /* check mode/owner on _PATH_SUDOERS */ + /* Update initial shell now that runas is set. */ + if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) + NewArgv[0] = runas_pw->pw_shell; - /* Local sudoers file overrides LDAP if we have a match. */ - v = sudoers_lookup(pwflag); - if (validated == VALIDATE_ERROR || ISSET(v, VALIDATE_OK)) - validated = v; + /* This goes after sudoers is parsed since it may have timestamp options. */ + if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) { + remove_timestamp((sudo_mode == MODE_KILL)); + cleanup(0); + exit(0); } -#else - check_sudoers(); /* check mode/owner on _PATH_SUDOERS */ - /* Validate the user but don't search for pseudo-commands. */ - validated = sudoers_lookup(pwflag); + /* Is root even allowed to run sudo? */ + if (user_uid == 0 && !def_root_sudo) { + (void) fprintf(stderr, + "Sorry, %s has been configured to not allow root to run it.\n", + getprogname()); + exit(1); + } + + /* Check for -C overriding def_closefrom. */ + if (user_closefrom >= 0 && user_closefrom != def_closefrom) { + if (!def_closefrom_override) + errorx(1, "you are not permitted to use the -C option"); + else + def_closefrom = user_closefrom; + } + + cmnd_status = set_cmnd(sudo_mode); + +#ifdef HAVE_SETLOCALE + if (!setlocale(LC_ALL, def_sudoers_locale)) { + warningx("unable to set locale to \"%s\", using \"C\"", + def_sudoers_locale); + setlocale(LC_ALL, "C"); + } #endif + + validated = FLAG_NO_USER | FLAG_NO_HOST; + tq_foreach_fwd(snl, nss) { + validated = nss->lookup(nss, validated, pwflag); + + /* Handle [NOTFOUND=return] */ + if (!ISSET(validated, VALIDATE_OK) && nss->ret_notfound) + break; + } if (safe_cmnd == NULL) safe_cmnd = estrdup(user_cmnd); +#ifdef HAVE_SETLOCALE + setlocale(LC_ALL, ""); +#endif + + /* If only a group was specified, set runas_pw based on invoking user. */ + if (runas_pw == NULL) + set_runaspw(user_name); + /* * Look up the timestamp dir owner if one is specified. */ @@ -297,33 +363,15 @@ main(argc, argv, envp) struct passwd *pw; if (*def_timestampowner == '#') - pw = getpwuid(atoi(def_timestampowner + 1)); + pw = sudo_getpwuid(atoi(def_timestampowner + 1)); else - pw = getpwnam(def_timestampowner); + pw = sudo_getpwnam(def_timestampowner); if (!pw) log_error(0, "timestamp owner (%s): No such user", def_timestampowner); timestamp_uid = pw->pw_uid; } - /* This goes after the sudoers parse since we honor sudoers options. */ - if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) { - remove_timestamp((sudo_mode == MODE_KILL)); - exit(0); - } - - if (ISSET(validated, VALIDATE_ERROR)) - log_error(0, "parse error in %s near line %d", _PATH_SUDOERS, - errorlineno); - - /* Is root even allowed to run sudo? */ - if (user_uid == 0 && !def_root_sudo) { - (void) fprintf(stderr, - "Sorry, %s has been configured to not allow root to run it.\n", - getprogname()); - exit(1); - } - /* If given the -P option, set the "preserve_groups" flag. */ if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS)) def_preserve_groups = TRUE; @@ -340,42 +388,44 @@ main(argc, argv, envp) (void) close(fd); } - /* User may have overriden environment resetting via the -E flag. */ - if (ISSET(sudo_mode, MODE_PRESERVE_ENV) && ISSET(validated, FLAG_SETENV)) + /* Use askpass value from sudoers unless user specified their own. */ + if (def_askpass && !user_askpass) + user_askpass = def_askpass; + + /* User may have overridden environment resetting via the -E flag. */ + if (ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv) def_env_reset = FALSE; /* Build a new environment that avoids any nasty bits. */ - environ = rebuild_env(environ, sudo_mode, ISSET(validated, FLAG_NOEXEC)); + rebuild_env(sudo_mode, def_noexec); /* Fill in passwd struct based on user we are authenticating as. */ auth_pw = get_authpw(); /* Require a password if sudoers says so. */ - if (!ISSET(validated, FLAG_NOPASS)) - check_user(validated); + if (def_authenticate) + check_user(validated, !ISSET(sudo_mode, MODE_NONINTERACTIVE)); /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */ - if (user_uid == 0 && prev_user != NULL && strcmp(prev_user, "root") != 0) { + /* XXX - causes confusion when root is not listed in sudoers */ + if (sudo_mode & (MODE_RUN | MODE_EDIT) && prev_user != NULL) { + if (user_uid == 0 && strcmp(prev_user, "root") != 0) { struct passwd *pw; - if ((pw = sudo_getpwnam(prev_user)) != NULL) { - efree(sudo_user.pw); + if ((pw = sudo_getpwnam(prev_user)) != NULL) sudo_user.pw = pw; - } + } } if (ISSET(validated, VALIDATE_OK)) { /* Finally tell the user if the command did not exist. */ - if (cmnd_status == NOT_FOUND_DOT) { - warnx("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd); - exit(1); - } else if (cmnd_status == NOT_FOUND) { - warnx("%s: command not found", user_cmnd); - exit(1); - } + if (cmnd_status == NOT_FOUND_DOT) + 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) + errorx(1, "%s: command not found", user_cmnd); /* If user specified env vars make sure sudoers allows it. */ - if (ISSET(sudo_mode, MODE_RUN) && !ISSET(validated, FLAG_SETENV)) { + if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) { if (ISSET(sudo_mode, MODE_PRESERVE_ENV)) log_error(NO_MAIL, "sorry, you are not allowed to preserve the environment"); @@ -383,20 +433,31 @@ main(argc, argv, envp) validate_env_vars(sudo_user.env_vars); } - log_auth(validated, 1); - if (sudo_mode == MODE_VALIDATE) - exit(0); - else if (sudo_mode == MODE_LIST) { - list_matches(); -#ifdef HAVE_LDAP - sudo_ldap_list_matches(); -#endif - exit(0); - } + log_allowed(validated); + if (sudo_mode == MODE_CHECK) + rc = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw); + else if (sudo_mode == MODE_LIST) + display_privs(snl, list_pw ? list_pw : sudo_user.pw); + + /* Cleanup sudoers sources */ + tq_foreach_fwd(snl, nss) + nss->close(nss); + + /* Deferred exit due to sudo_ldap_close() */ + if (sudo_mode == MODE_VALIDATE || sudo_mode == MODE_CHECK || + sudo_mode == MODE_LIST) + exit(rc); - /* Override user's umask if configured to do so. */ - if (def_umask != 0777) - (void) umask(def_umask); + /* + * Override user's umask if configured to do so. + * If user's umask is more restrictive, OR in those bits too. + */ + if (def_umask != 0777) { + mode_t mask = umask(def_umask); + mask |= def_umask; + if (mask != def_umask) + umask(mask); + } /* Restore coredumpsize resource limit. */ #if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) @@ -407,10 +468,6 @@ main(argc, argv, envp) if (ISSET(sudo_mode, MODE_RUN)) set_perms(PERM_FULL_RUNAS); - /* Close the password and group files */ - endpwent(); - endgrent(); - if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { char *p; @@ -422,49 +479,63 @@ main(argc, argv, envp) /* Change to target user's homedir. */ if (chdir(runas_pw->pw_dir) == -1) - warn("unable to change directory to %s", runas_pw->pw_dir); + warning("unable to change directory to %s", runas_pw->pw_dir); + +#if defined(__linux__) || defined(_AIX) + /* Insert system-wide environment variables. */ + read_env_file(_PATH_ENVIRONMENT, TRUE); +#endif } if (ISSET(sudo_mode, MODE_EDIT)) exit(sudo_edit(NewArgc, NewArgv, envp)); + /* Insert system-wide environment variables. */ + if (def_env_file) + read_env_file(def_env_file, FALSE); + /* Insert user-specified environment variables. */ - environ = insert_env_vars(environ, sudo_user.env_vars); + insert_env_vars(sudo_user.env_vars); /* Restore signal handlers before we exec. */ (void) sigaction(SIGINT, &saved_sa_int, NULL); (void) sigaction(SIGQUIT, &saved_sa_quit, NULL); (void) sigaction(SIGTSTP, &saved_sa_tstp, NULL); + /* Close the password and group files and free up memory. */ + sudo_endpwent(); + sudo_endgrent(); + + closefrom(def_closefrom + 1); + #ifndef PROFILING if (ISSET(sudo_mode, MODE_BACKGROUND) && fork() > 0) exit(0); else { #ifdef HAVE_SELINUX if (is_selinux_enabled() > 0 && user_role != NULL) - selinux_exec(user_role, user_type, NewArgv, environ, + selinux_exec(user_role, user_type, NewArgv, ISSET(sudo_mode, MODE_LOGIN_SHELL)); #endif - execve(safe_cmnd, NewArgv, environ); + execv(safe_cmnd, NewArgv); } #else exit(0); #endif /* PROFILING */ /* - * If we got here then the exec() failed... + * If we got here then execve() failed... */ if (errno == ENOEXEC) { NewArgv--; /* at least one extra slot... */ NewArgv[0] = "sh"; NewArgv[1] = safe_cmnd; - execve(_PATH_BSHELL, NewArgv, environ); - } - warn("unable to execute %s", safe_cmnd); + execv(_PATH_BSHELL, NewArgv); + } warning("unable to execute %s", safe_cmnd); exit(127); - } else if (ISSET(validated, FLAG_NO_USER) || (validated & FLAG_NO_HOST)) { - log_auth(validated, 1); + } else if (ISSET(validated, FLAG_NO_USER | FLAG_NO_HOST)) { + log_denial(validated, 1); exit(1); - } else if (ISSET(validated, VALIDATE_NOT_OK)) { + } else { if (def_path_info) { /* * We'd like to not leak path info at all here, but that can @@ -473,21 +544,17 @@ main(argc, argv, envp) * is just "no foo in path" since the user can trivially set * their path to just contain a single dir. */ - log_auth(validated, + log_denial(validated, !(cmnd_status == NOT_FOUND_DOT || cmnd_status == NOT_FOUND)); if (cmnd_status == NOT_FOUND) - warnx("%s: command not found", user_cmnd); + warningx("%s: command not found", user_cmnd); else if (cmnd_status == NOT_FOUND_DOT) - warnx("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd); + warningx("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd); } else { /* Just tell the user they are not allowed to run foo. */ - log_auth(validated, 1); + log_denial(validated, 1); } exit(1); - } else { - /* should never get here */ - log_auth(validated, 1); - exit(1); } exit(0); /* not reached */ } @@ -496,17 +563,17 @@ main(argc, argv, envp) * Initialize timezone, set umask, fill in ``sudo_user'' struct and * load the ``interfaces'' array. */ -static int +static void init_vars(sudo_mode, envp) int sudo_mode; char **envp; { - char *p, **ep, thost[MAXHOSTNAMELEN]; - int nohostname, rval; + char *p, **ep, thost[MAXHOSTNAMELEN + 1]; + int nohostname; /* Sanity check command from user. */ if (user_cmnd == NULL && strlen(NewArgv[0]) >= PATH_MAX) - errx(1, "%s: File name too long", NewArgv[0]); + errorx(1, "%s: File name too long", NewArgv[0]); #ifdef HAVE_TZSET (void) tzset(); /* set the timezone if applicable */ @@ -527,6 +594,7 @@ init_vars(sudo_mode, envp) if (nohostname) user_host = user_shost = "localhost"; else { + thost[sizeof(thost) - 1] = '\0'; user_host = estrdup(thost); if (def_fqdn) { /* Defer call to set_fqdn() until log_error() is safe. */ @@ -550,7 +618,16 @@ init_vars(sudo_mode, envp) user_tty = "unknown"; for (ep = envp; *ep; ep++) { + /* XXX - don't fill in if empty string */ switch (**ep) { + case 'D': + if (strncmp("DISPLAY=", *ep, 8) == 0) + user_display = *ep + 8; + break; + case 'K': + if (strncmp("KRB5CCNAME=", *ep, 11) == 0) + user_ccname = *ep + 11; + break; case 'P': if (strncmp("PATH=", *ep, 5) == 0) user_path = *ep + 5; @@ -562,8 +639,9 @@ init_vars(sudo_mode, envp) user_prompt = *ep + 12; else if (strncmp("SUDO_USER=", *ep, 10) == 0) prev_user = *ep + 10; + else if (strncmp("SUDO_ASKPASS=", *ep, 13) == 0) + user_askpass = *ep + 13; break; - } } @@ -589,11 +667,11 @@ init_vars(sudo_mode, envp) * be run during reboot after the YP/NIS/NIS+/LDAP/etc daemon has died. */ if (sudo_mode & (MODE_INVALIDATE|MODE_KILL)) - errx(1, "uid %s does not exist in the passwd file!", pw_name); - log_error(0, "uid %s does not exist in the passwd file!", pw_name); + errorx(1, "unknown uid: %s", pw_name); + log_error(0, "unknown uid: %s", pw_name); } if (user_shell == NULL || *user_shell == '\0') - user_shell = sudo_user.pw->pw_shell; + user_shell = estrdup(sudo_user.pw->pw_shell); /* It is now safe to use log_error() and set_perms() */ @@ -612,10 +690,6 @@ init_vars(sudo_mode, envp) if (nohostname) log_error(USE_ERRNO|MSG_ONLY, "can't get hostname"); - set_runaspw(*user_runas); /* may call log_error() */ - if (*user_runas[0] == '#' && runas_pw->pw_name && runas_pw->pw_name[0]) - *user_runas = estrdup(runas_pw->pw_name); - /* * Get current working directory. Try as user, fall back to root. */ @@ -623,7 +697,7 @@ init_vars(sudo_mode, envp) if (!getcwd(user_cwd, sizeof(user_cwd))) { set_perms(PERM_ROOT); if (!getcwd(user_cwd, sizeof(user_cwd))) { - warnx("cannot get working directory"); + warningx("cannot get working directory"); (void) strlcpy(user_cwd, "unknown", sizeof(user_cwd)); } } else @@ -633,28 +707,47 @@ init_vars(sudo_mode, envp) * If we were given the '-e', '-i' or '-s' options we need to redo * NewArgv and NewArgc. */ - if ((sudo_mode & (MODE_SHELL | MODE_EDIT))) { - char **dst, **src = NewArgv; + if (ISSET(sudo_mode, MODE_EDIT)) { + NewArgv--; + NewArgc++; + NewArgv[0] = "sudoedit"; + } else if (ISSET(sudo_mode, MODE_SHELL)) { + char **av; /* Allocate an extra slot for execve() failure (ENOEXEC). */ - NewArgv = (char **) emalloc2((++NewArgc + 2), sizeof(char *)); - NewArgv++; - if (ISSET(sudo_mode, MODE_EDIT)) - NewArgv[0] = "sudoedit"; - else if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) - NewArgv[0] = runas_pw->pw_shell; - else if (user_shell && *user_shell) - NewArgv[0] = user_shell; - else - errx(1, "unable to determine shell"); - - /* copy the args from NewArgv */ - for (dst = NewArgv + 1; (*dst = *src) != NULL; ++src, ++dst) - continue; + av = (char **) emalloc2(5, sizeof(char *)); + av++; + + av[0] = user_shell; /* may be updated later */ + if (NewArgc > 0) { + size_t size; + char *cmnd, *src, *dst, *end; + size = (size_t) (NewArgv[NewArgc - 1] - NewArgv[0]) + + strlen(NewArgv[NewArgc - 1]) + 1; + cmnd = emalloc(size); + src = NewArgv[0]; + dst = cmnd; + for (end = src + size - 1; src < end; src++, dst++) + *dst = *src == 0 ? ' ' : *src; + *dst = '\0'; + av[1] = "-c"; + av[2] = cmnd; + NewArgc = 2; + } + av[++NewArgc] = NULL; + NewArgv = av; } +} - /* Set login class if applicable. */ - set_loginclass(sudo_user.pw); +/* + * Fill in user_cmnd, user_args, user_base and user_stat variables + * and apply any command-specific defaults entries. + */ +static int +set_cmnd(sudo_mode) + int sudo_mode; +{ + int rval; /* Set project if applicable. */ set_project(runas_pw); @@ -662,9 +755,8 @@ init_vars(sudo_mode, envp) /* Resolve the path and return. */ rval = FOUND; user_stat = emalloc(sizeof(struct stat)); - if (sudo_mode & (MODE_RUN | MODE_EDIT)) { - if (ISSET(sudo_mode, MODE_RUN)) { - /* XXX - default_runas may be modified during parsing of sudoers */ + if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { + if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) { set_perms(PERM_RUNAS); rval = find_path(NewArgv[0], &user_cmnd, user_stat, user_path); set_perms(PERM_ROOT); @@ -682,7 +774,7 @@ init_vars(sudo_mode, envp) size_t size, n; /* If we didn't realloc NewArgv it is contiguous so just count. */ - if (!(sudo_mode & (MODE_SHELL | MODE_EDIT))) { + if (!ISSET(sudo_mode, MODE_SHELL)) { size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) + strlen(NewArgv[NewArgc-1]) + 1; } else { @@ -695,7 +787,7 @@ init_vars(sudo_mode, envp) for (to = user_args, from = NewArgv + 1; *from; from++) { n = strlcpy(to, *from, size - (to - user_args)); if (n >= size - (to - user_args)) - errx(1, "internal error, init_vars() overflow"); + errorx(1, "internal error, init_vars() overflow"); to += n; *to++ = ' '; } @@ -707,265 +799,259 @@ init_vars(sudo_mode, envp) else user_base = user_cmnd; + if (!update_defaults(SETDEF_CMND)) + log_error(NO_STDERR|NO_EXIT, "problem with defaults entries"); + return(rval); } /* - * Command line argument parsing, can't use getopt(3). + * Command line argument parsing. + * Sets NewArgc and NewArgv which corresponds to the argc/argv we'll use + * for the command to be run (if we are running one). */ static int parse_args(argc, argv) int argc; char **argv; { - int rval = MODE_RUN; /* what mode is sudo to be run in? */ - int excl = 0; /* exclusive arg, no others allowed */ - - NewArgv = argv + 1; - NewArgc = argc - 1; + int mode = 0; /* what mode is sudo to be run in? */ + int flags = 0; /* mode flags */ + int ch; /* First, check to see if we were invoked as "sudoedit". */ - if (strcmp(getprogname(), "sudoedit") == 0) { - rval = MODE_EDIT; - excl = 'e'; - } else - rval = MODE_RUN; - - while (NewArgc > 0) { - if (NewArgv[0][0] == '-') { - if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0') { - warnx("please use single character options"); - usage(1); - } - - switch (NewArgv[0][1]) { - case 'p': - /* Must have an associated prompt. */ - if (NewArgv[1] == NULL) - usage(1); + if (strcmp(getprogname(), "sudoedit") == 0) + mode = MODE_EDIT; - user_prompt = NewArgv[1]; - def_passprompt_override = TRUE; + /* Returns true if the last option string was "--" */ +#define got_end_of_args (optind > 1 && argv[optind - 1][0] == '-' && \ + argv[optind - 1][1] == '-' && argv[optind - 1][2] == '\0') - NewArgc--; - NewArgv++; - break; - case 'u': - /* Must have an associated runas user. */ - if (NewArgv[1] == NULL) - usage(1); + /* Returns true if next option is an environment variable */ +#define is_envar (optind < argc && argv[optind][0] != '/' && \ + strchr(argv[optind], '=') != NULL) - user_runas = &NewArgv[1]; - - NewArgc--; - NewArgv++; + for (;;) { + /* + * We disable arg permutation for GNU getopt(). + * Some trickiness is required to allow environment variables + * to be interspersed with command line options. + */ + if ((ch = getopt(argc, argv, "+Aa:bC:c:Eeg:HhiKkLlnPp:r:Sst:U:u:Vv")) != -1) { + switch (ch) { + case 'A': + SET(tgetpass_flags, TGP_ASKPASS); break; #ifdef HAVE_BSD_AUTH_H case 'a': - /* Must have an associated authentication style. */ - if (NewArgv[1] == NULL) - usage(1); - - login_style = NewArgv[1]; - - NewArgc--; - NewArgv++; + login_style = optarg; break; #endif + case 'b': + SET(flags, MODE_BACKGROUND); + break; + case 'C': + if ((user_closefrom = atoi(optarg)) < 3) { + warningx("the argument to -C must be at least 3"); + usage(1); + } + break; #ifdef HAVE_LOGIN_CAP_H case 'c': - /* Must have an associated login class. */ - if (NewArgv[1] == NULL) - usage(1); - - login_class = NewArgv[1]; + login_class = optarg; def_use_loginclass = TRUE; - - NewArgc--; - NewArgv++; break; #endif - case 'b': - SET(rval, MODE_BACKGROUND); + case 'E': + SET(flags, MODE_PRESERVE_ENV); break; case 'e': - rval = MODE_EDIT; - if (excl && excl != 'e') + if (mode && mode != MODE_EDIT) usage_excl(1); - excl = 'e'; + mode = MODE_EDIT; break; - case 'v': - rval = MODE_VALIDATE; - if (excl && excl != 'v') + case 'g': + runas_group = optarg; + break; + case 'H': + SET(flags, MODE_RESET_HOME); + break; + case 'h': + if (mode && mode != MODE_HELP) usage_excl(1); - excl = 'v'; + mode = MODE_HELP; break; case 'i': - SET(rval, (MODE_LOGIN_SHELL | MODE_SHELL)); + SET(flags, MODE_LOGIN_SHELL); def_env_reset = TRUE; - if (excl && excl != 'i') - usage_excl(1); - excl = 'i'; break; case 'k': - rval = MODE_INVALIDATE; - if (excl && excl != 'k') + if (mode && mode != MODE_INVALIDATE) usage_excl(1); - excl = 'k'; + mode = MODE_INVALIDATE; break; case 'K': - rval = MODE_KILL; - if (excl && excl != 'K') + if (mode && mode != MODE_KILL) usage_excl(1); - excl = 'K'; + mode = MODE_KILL; break; case 'L': - rval = MODE_LISTDEFS; - if (excl && excl != 'L') + if (mode && mode != MODE_LISTDEFS) usage_excl(1); - excl = 'L'; + mode = MODE_LISTDEFS; break; case 'l': - rval = MODE_LIST; - if (excl && excl != 'l') - usage_excl(1); - excl = 'l'; + if (mode) { + if (mode == MODE_LIST) + long_list = 1; + else + usage_excl(1); + } + mode = MODE_LIST; break; - case 'V': - rval = MODE_VERSION; - if (excl && excl != 'V') - usage_excl(1); - excl = 'V'; + case 'n': + SET(flags, MODE_NONINTERACTIVE); break; - case 'h': - rval = MODE_HELP; - if (excl && excl != 'h') - usage_excl(1); - excl = 'h'; + case 'P': + SET(flags, MODE_PRESERVE_GROUPS); break; - case 's': - SET(rval, MODE_SHELL); - if (excl && excl != 's') - usage_excl(1); - excl = 's'; + case 'p': + user_prompt = optarg; + def_passprompt_override = TRUE; break; - case 'H': - SET(rval, MODE_RESET_HOME); +#ifdef HAVE_SELINUX + case 'r': + user_role = optarg; break; - case 'P': - SET(rval, MODE_PRESERVE_GROUPS); + case 't': + user_type = optarg; break; +#endif case 'S': SET(tgetpass_flags, TGP_STDIN); break; - case 'E': - SET(rval, MODE_PRESERVE_ENV); + case 's': + SET(flags, MODE_SHELL); break; -#ifdef HAVE_SELINUX - case 'r': - /* Must have an associated SELinux role. */ - if (NewArgv[1] == NULL) - usage(1); - - user_role = NewArgv[1]; - - NewArgc--; - NewArgv++; + case 'U': + if ((list_pw = sudo_getpwnam(optarg)) == NULL) + errorx(1, "unknown user: %s", optarg); break; - case 't': - /* Must have an associated SELinux type. */ - if (NewArgv[1] == NULL) - usage(1); - - user_type = NewArgv[1]; - - NewArgc--; - NewArgv++; + case 'u': + runas_user = optarg; + break; + case 'v': + if (mode && mode != MODE_VALIDATE) + usage_excl(1); + mode = MODE_VALIDATE; + break; + case 'V': + if (mode && mode != MODE_VERSION) + usage_excl(1); + mode = MODE_VERSION; break; -#endif - case '-': - NewArgc--; - NewArgv++; - goto args_done; - case '\0': - warnx("'-' requires an argument"); - usage(1); default: - warnx("illegal option `%s'", NewArgv[0]); usage(1); } - } else if (NewArgv[0][0] != '/' && strchr(NewArgv[0], '=') != NULL) { - /* Could be an environment variable. */ + } else if (!got_end_of_args && is_envar) { struct list_member *ev; + + /* Store environment variable. */ ev = emalloc(sizeof(*ev)); - ev->value = NewArgv[0]; + ev->value = argv[optind]; ev->next = sudo_user.env_vars; sudo_user.env_vars = ev; + + /* Crank optind and resume getopt. */ + optind++; } else { - /* Not an arg */ + /* Not an option or an environment variable -- we're done. */ break; } - NewArgc--; - NewArgv++; } -args_done: - if (ISSET(rval, MODE_EDIT) && - (ISSET(rval, MODE_PRESERVE_ENV) || sudo_user.env_vars != NULL)) { - if (ISSET(rval, MODE_PRESERVE_ENV)) - warnx("the `-E' option is not valid in edit mode"); + NewArgc = argc - optind; + NewArgv = argv + optind; + + if (!mode) + mode = MODE_RUN; + + if (NewArgc > 0 && mode == MODE_LIST) + mode = MODE_CHECK; + + if (ISSET(flags, MODE_LOGIN_SHELL)) { + if (ISSET(flags, MODE_SHELL)) { + warningx("you may not specify both the `-i' and `-s' options"); + usage(1); + } + if (ISSET(flags, MODE_PRESERVE_ENV)) { + warningx("you may not specify both the `-i' and `-E' options"); + usage(1); + } + SET(flags, MODE_SHELL); + } + if (mode == MODE_EDIT && + (ISSET(flags, MODE_PRESERVE_ENV) || sudo_user.env_vars != NULL)) { + if (ISSET(mode, MODE_PRESERVE_ENV)) + warningx("the `-E' option is not valid in edit mode"); if (sudo_user.env_vars != NULL) - warnx("you may not specify environment variables in edit mode"); + warningx("you may not specify environment variables in edit mode"); + usage(1); + } + if ((runas_user != NULL || runas_group != NULL) && + !ISSET(mode, MODE_EDIT | MODE_RUN | MODE_CHECK)) { usage(1); } - if (ISSET(rval, MODE_PRESERVE_ENV) && ISSET(rval, MODE_LOGIN_SHELL)) { - warnx("you may not specify both the `-i' and `-E' options"); + if (list_pw != NULL && mode != MODE_LIST && mode != MODE_CHECK) { + warningx("the `-U' option may only be used with the `-l' option"); usage(1); } - if (user_runas != NULL && !ISSET(rval, (MODE_EDIT|MODE_RUN))) { - if (excl != '\0') - warnx("the `-u' and '-%c' options may not be used together", excl); + if (ISSET(tgetpass_flags, TGP_STDIN) && ISSET(tgetpass_flags, TGP_ASKPASS)) { + warningx("the `-A' and `-S' options may not be used together"); usage(1); } - if ((NewArgc == 0 && (rval & MODE_EDIT)) || - (NewArgc > 0 && !(rval & (MODE_RUN | MODE_EDIT)))) + if ((NewArgc == 0 && mode == MODE_EDIT) || + (NewArgc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK))) usage(1); - if (NewArgc == 0 && rval == MODE_RUN) - SET(rval, (MODE_IMPLIED_SHELL | MODE_SHELL)); + if (NewArgc == 0 && mode == MODE_RUN && !ISSET(flags, MODE_SHELL)) + SET(flags, (MODE_IMPLIED_SHELL | MODE_SHELL)); - return(rval); + return(mode | flags); } /* - * Sanity check sudoers mode/owner/type. - * Leaves a file pointer to the sudoers file open in ``fp''. + * Open sudoers and sanity check mode/owner/type. + * Returns a handle to the sudoers file or NULL on error. */ -static void -check_sudoers() +FILE * +open_sudoers(sudoers, keepopen) + const char *sudoers; + int *keepopen; { struct stat statbuf; - int rootstat, i; + FILE *fp = NULL; + int rootstat; /* * Fix the mode and group on sudoers file from old default. * Only works if file system is readable/writable by root. */ - if ((rootstat = stat_sudoers(_PATH_SUDOERS, &statbuf)) == 0 && + if ((rootstat = stat_sudoers(sudoers, &statbuf)) == 0 && SUDOERS_UID == statbuf.st_uid && SUDOERS_MODE != 0400 && (statbuf.st_mode & 0007777) == 0400) { - if (chmod(_PATH_SUDOERS, SUDOERS_MODE) == 0) { - warnx("fixed mode on %s", _PATH_SUDOERS); + if (chmod(sudoers, SUDOERS_MODE) == 0) { + warningx("fixed mode on %s", sudoers); SET(statbuf.st_mode, SUDOERS_MODE); if (statbuf.st_gid != SUDOERS_GID) { - if (!chown(_PATH_SUDOERS,(uid_t) -1,SUDOERS_GID)) { - warnx("set group on %s", _PATH_SUDOERS); + if (chown(sudoers, (uid_t) -1, SUDOERS_GID) == 0) { + warningx("set group on %s", sudoers); statbuf.st_gid = SUDOERS_GID; } else - warn("unable to set group on %s", _PATH_SUDOERS); + warning("unable to set group on %s", sudoers); } } else - warn("unable to fix mode on %s", _PATH_SUDOERS); + warning("unable to fix mode on %s", sudoers); } /* @@ -975,46 +1061,40 @@ check_sudoers() */ set_perms(PERM_SUDOERS); - if (rootstat != 0 && stat_sudoers(_PATH_SUDOERS, &statbuf) != 0) - log_error(USE_ERRNO, "can't stat %s", _PATH_SUDOERS); + if (rootstat != 0 && stat_sudoers(sudoers, &statbuf) != 0) + log_error(USE_ERRNO|NO_EXIT, "can't stat %s", sudoers); else if (!S_ISREG(statbuf.st_mode)) - log_error(0, "%s is not a regular file", _PATH_SUDOERS); - else if (statbuf.st_size == 0) - log_error(0, "%s is zero length", _PATH_SUDOERS); + log_error(NO_EXIT, "%s is not a regular file", sudoers); else if ((statbuf.st_mode & 07777) != SUDOERS_MODE) - log_error(0, "%s is mode 0%o, should be 0%o", _PATH_SUDOERS, + log_error(NO_EXIT, "%s is mode 0%o, should be 0%o", sudoers, (unsigned int) (statbuf.st_mode & 07777), (unsigned int) SUDOERS_MODE); else if (statbuf.st_uid != SUDOERS_UID) - log_error(0, "%s is owned by uid %lu, should be %lu", _PATH_SUDOERS, + log_error(NO_EXIT, "%s is owned by uid %lu, should be %lu", sudoers, (unsigned long) statbuf.st_uid, (unsigned long) SUDOERS_UID); else if (statbuf.st_gid != SUDOERS_GID) - log_error(0, "%s is owned by gid %lu, should be %lu", _PATH_SUDOERS, + log_error(NO_EXIT, "%s is owned by gid %lu, should be %lu", sudoers, (unsigned long) statbuf.st_gid, (unsigned long) SUDOERS_GID); - else { - /* Solaris sometimes returns EAGAIN so try 10 times */ - for (i = 0; i < 10 ; i++) { - errno = 0; - if ((sudoers_fp = fopen(_PATH_SUDOERS, "r")) == NULL || - fgetc(sudoers_fp) == EOF) { - if (sudoers_fp != NULL) - fclose(sudoers_fp); - sudoers_fp = NULL; - if (errno != EAGAIN && errno != EWOULDBLOCK) - break; - } else - break; - sleep(1); - } - if (sudoers_fp == NULL) - log_error(USE_ERRNO, "can't open %s", _PATH_SUDOERS); + else if ((fp = fopen(sudoers, "r")) == NULL) + log_error(USE_ERRNO, "can't open %s", sudoers); + else if (statbuf.st_size != 0) { + /* + * Make sure we can actually read sudoers so we can present the + * user with a reasonable error message. + */ + if (fgetc(fp) == EOF) + log_error(USE_ERRNO, "can't read %s", sudoers); + rewind(fp); } + (void) fcntl(fileno(fp), F_SETFD, 1); set_perms(PERM_ROOT); /* change back to root */ + return(fp); } /* * Close all open files (except std*) and turn off core dumps. + * Also sets the set_perms() pointer to the correct function. */ static void initial_setup() @@ -1063,9 +1143,10 @@ initial_setup() (void) dup2(devnull, STDOUT_FILENO); if (miss[STDERR_FILENO]) (void) dup2(devnull, STDERR_FILENO); + if (devnull > STDERR_FILENO) + close(devnull); } } - closefrom(STDERR_FILENO + 1); } #ifdef HAVE_LOGIN_CAP_H @@ -1086,8 +1167,9 @@ set_loginclass(pw) errflags = NO_MAIL|MSG_ONLY|NO_EXIT; if (login_class && strcmp(login_class, "-") != 0) { - if (strcmp(*user_runas, "root") != 0 && user_uid != 0) - errx(1, "only root can use -c %s", login_class); + if (user_uid != 0 && + strcmp(runas_user ? runas_user : def_runas_default, "root") != 0) + errorx(1, "only root can use -c %s", login_class); } else { login_class = pw->pw_class; if (!login_class || !*login_class) @@ -1190,7 +1272,7 @@ set_fqdn() char *p; #ifdef HAVE_GETADDRINFO - memset(&hint, 0, sizeof(hint)); + zero_bytes(&hint, sizeof(hint)); hint.ai_family = PF_UNSPEC; hint.ai_flags = AI_CANONNAME; if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) { @@ -1223,28 +1305,34 @@ set_fqdn() * Get passwd entry for the user we are going to run commands as. * By default, this is "root". Updates runas_pw as a side effect. */ -int +static void set_runaspw(user) char *user; { - if (runas_pw != NULL) { - if (user_runas != &def_runas_default) - return(TRUE); /* don't override -u option */ - efree(runas_pw); - } if (*user == '#') { - runas_pw = sudo_getpwuid(atoi(user + 1)); - if (runas_pw == NULL) { - runas_pw = emalloc(sizeof(struct passwd)); - (void) memset((VOID *)runas_pw, 0, sizeof(struct passwd)); - runas_pw->pw_uid = atoi(user + 1); - } + if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL) + runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0); } else { - runas_pw = sudo_getpwnam(user); - if (runas_pw == NULL) - log_error(NO_MAIL|MSG_ONLY, "no passwd entry for %s!", user); + if ((runas_pw = sudo_getpwnam(user)) == NULL) + log_error(NO_MAIL|MSG_ONLY, "unknown user: %s", user); + } +} + +/* + * Get group entry for the group we are going to run commands as. + * Updates runas_pw as a side effect. + */ +static void +set_runasgr(group) + char *group; +{ + if (*group == '#') { + if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL) + runas_gr = sudo_fakegrnam(group); + } else { + if ((runas_gr = sudo_getgrnam(group)) == NULL) + log_error(NO_MAIL|MSG_ONLY, "unknown group: %s", group); } - return(TRUE); } /* @@ -1258,19 +1346,14 @@ get_authpw() struct passwd *pw; if (def_rootpw) { - if (runas_pw->pw_uid == 0) - pw = runas_pw; - else if ((pw = sudo_getpwuid(0)) == NULL) - log_error(0, "uid 0 does not exist in the passwd file!"); + if ((pw = sudo_getpwuid(0)) == NULL) + log_error(0, "unknown uid: 0"); } else if (def_runaspw) { - if (strcmp(def_runas_default, *user_runas) == 0) - pw = runas_pw; - else if ((pw = sudo_getpwnam(def_runas_default)) == NULL) - log_error(0, "user %s does not exist in the passwd file!", - def_runas_default); + if ((pw = sudo_getpwnam(def_runas_default)) == NULL) + log_error(0, "unknown user: %s", def_runas_default); } else if (def_targetpw) { if (runas_pw->pw_name == NULL) - log_error(NO_MAIL|MSG_ONLY, "no passwd entry for %lu!", + log_error(NO_MAIL|MSG_ONLY, "unknown uid: %lu", (unsigned long) runas_pw->pw_uid); pw = runas_pw; } else @@ -1279,6 +1362,46 @@ get_authpw() return(pw); } +/* + * Cleanup hook for error()/errorx() + */ +void +cleanup(gotsignal) + int gotsignal; +{ + struct sudo_nss *nss; + + if (!gotsignal) { + if (snl != NULL) { + tq_foreach_fwd(snl, nss) + nss->close(nss); + } + sudo_endpwent(); + sudo_endgrent(); + } +} + +static void +show_version() +{ + (void) printf("Sudo version %s\n", version); + if (getuid() == 0) { + putchar('\n'); + (void) printf("Sudoers path: %s\n", _PATH_SUDOERS); +#ifdef HAVE_LDAP +# ifdef _PATH_NSSWITCH_CONF + (void) printf("nsswitch path: %s\n", _PATH_NSSWITCH_CONF); +# endif + (void) printf("ldap.conf path: %s\n", _PATH_LDAP_CONF); + (void) printf("ldap.secret path: %s\n", _PATH_LDAP_SECRET); +#endif + dump_auth_methods(); + dump_defaults(); + dump_interfaces(); + } + exit(0); +} + /* * Tell which options are mutually exclusive and exit. */ @@ -1286,98 +1409,46 @@ static void usage_excl(exit_val) int exit_val; { - warnx("Only one of the -e, -h, i, -k, -K, -l, -s, -v or -V options may be used"); + warningx("Only one of the -e, -h, -i, -k, -K, -l, -s, -v or -V options may be specified"); usage(exit_val); } /* * Give usage message and exit. + * The actual usage strings are in sudo_usage.h for configure substitution. */ static void usage(exit_val) int exit_val; { - char **p, **uvec[4]; - int i, linelen, linemax, ulen, plen; - static char *uvec1[] = { - " -h |", - " -K |", - " -k |", - " -L |", - " -l |", - " -V |", - " -v", - NULL - }; - static char *uvec2[] = { - " [-bEHPS]", -#ifdef HAVE_BSD_AUTH_H - " [-a auth_type]", -#endif -#ifdef HAVE_LOGIN_CAP_H - " [-c class|-]", -#endif -#ifdef HAVE_SELINUX - " [-r role]", -#endif - " [-p prompt]", -#ifdef HAVE_SELINUX - " [-t type]", -#endif - " [-u username|#uid]", - " [VAR=value]", - " {-i | -s | }", - NULL - }; - static char *uvec3[] = { - " -e", - " [-S]", -#ifdef HAVE_BSD_AUTH_H - " [-a auth_type]", -#endif -#ifdef HAVE_LOGIN_CAP_H - " [-c class|-]", -#endif - " [-p prompt]", - " [-u username|#uid]", - " file ...", - NULL - }; + struct lbuf lbuf; + char *uvec[5]; + int i, ulen; /* * Use usage vectors appropriate to the progname. */ if (strcmp(getprogname(), "sudoedit") == 0) { - uvec[0] = uvec3 + 1; + uvec[0] = SUDO_USAGE4 + 3; uvec[1] = NULL; } else { - uvec[0] = uvec1; - uvec[1] = uvec2; - uvec[2] = uvec3; - uvec[3] = NULL; + uvec[0] = SUDO_USAGE1; + uvec[1] = SUDO_USAGE2; + uvec[2] = SUDO_USAGE3; + uvec[3] = SUDO_USAGE4; + uvec[4] = NULL; } /* - * Print usage and wrap lines as needed. - * Assumes an 80-character wide terminal, which is kind of bogus... + * Print usage and wrap lines as needed, depending on the + * tty width. */ - ulen = (int)strlen(getprogname()) + 7; - linemax = 80; + ulen = (int)strlen(getprogname()) + 8; + lbuf_init(&lbuf, NULL, ulen, 0); for (i = 0; uvec[i] != NULL; i++) { - printf("usage: %s", getprogname()); - linelen = linemax - ulen; - for (p = uvec[i]; *p != NULL; p++) { - plen = (int)strlen(*p); - if (linelen >= plen || linelen == linemax - ulen) { - fputs(*p, stdout); - linelen -= plen; - } else { - p--; - linelen = linemax - ulen; - printf("\n%*s", ulen, ""); - } - } - putchar('\n'); + lbuf_append(&lbuf, "usage: ", getprogname(), uvec[i], NULL); + lbuf_print(&lbuf); } + lbuf_destroy(&lbuf); exit(exit_val); } diff --git a/sudo.cat b/sudo.cat index febd93b..07290ee 100644 --- a/sudo.cat +++ b/sudo.cat @@ -8,60 +8,60 @@ NNAAMMEE sudo, sudoedit - execute a command as another user SSYYNNOOPPSSIISS - ssuuddoo --hh | --KK | --kk | --LL | --ll | --VV | --vv + ssuuddoo [--nn] --hh | --KK | --kk | --LL | --VV | --vv - ssuuddoo [--bbEEHHPPSS] [--aa _a_u_t_h___t_y_p_e] [--cc _c_l_a_s_s|_-] [--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} + 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] - ssuuddooeeddiitt [--SS] [--aa _a_u_t_h___t_y_p_e] [--cc _c_l_a_s_s|_-] [--pp _p_r_o_m_p_t] - [--uu _u_s_e_r_n_a_m_e|_#_u_i_d] file ... + 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] + + ssuuddooeeddiitt [--AAnnSS] [--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] file ... DDEESSCCRRIIPPTTIIOONN - ssuuddoo allows a permitted user to execute a _c_o_m_m_a_n_d as the - superuser or another user, as specified in the _s_u_d_o_e_r_s - file. The real and effective uid and gid are set to match - those of the target user as specified in the passwd file - and the group vector is initialized based on the group - file (unless the --PP option was specified). If the invok­ - ing user is root or if the target user is the same as the - invoking user, no password is required. Otherwise, ssuuddoo - requires that users authenticate themselves with a pass­ - word by default (NOTE: in the default configuration this - is the user's password, not the root password). Once a - user has been authenticated, a timestamp is updated and - the user may then use sudo without a password for a short - period of time (5 minutes unless overridden in _s_u_d_o_e_r_s). + ssuuddoo allows a permitted user to execute a _c_o_m_m_a_n_d as the superuser or + another user, as specified in the _s_u_d_o_e_r_s file. The real and effective + uid and gid are set to match those of the target user as specified in + the passwd file and the group vector is initialized based on the group + file (unless the --PP option was specified). If the invoking user is + root or if the target user is the same as the invoking user, no + password is required. Otherwise, ssuuddoo requires that users authenticate + themselves with a password by default (NOTE: in the default + configuration this is the user's password, not the root password). + Once a user has been authenticated, a timestamp is updated and the user + may then use sudo without a password for a short period of time (5 + minutes unless overridden in _s_u_d_o_e_r_s). + + When invoked as ssuuddooeeddiitt, the --ee option (described below), is implied. - When invoked as ssuuddooeeddiitt, the --ee option (described below), - is implied. + ssuuddoo determines who is an authorized user by consulting the file + _/_e_t_c_/_s_u_d_o_e_r_s. By running ssuuddoo with the --vv option, a user can update + the time stamp without running a _c_o_m_m_a_n_d. The password prompt itself + will also time out if the user's password is not entered within 5 + minutes (unless overridden via _s_u_d_o_e_r_s). - ssuuddoo determines who is an authorized user by consulting - the file _/_e_t_c_/_s_u_d_o_e_r_s. By giving ssuuddoo the --vv flag, a user - can update the time stamp without running a _c_o_m_m_a_n_d. The - password prompt itself will also time out if the user's - password is not entered within 5 minutes (unless overrid­ - den via _s_u_d_o_e_r_s). + If a user who is not listed in the _s_u_d_o_e_r_s file tries to run a command + via ssuuddoo, mail is sent to the proper authorities, as defined at + configure time or in the _s_u_d_o_e_r_s file (defaults to root). Note that + the mail will not be sent if an unauthorized user tries to run sudo + with the --ll or --vv option. This allows users to determine for + themselves whether or not they are allowed to use ssuuddoo. - If a user who is not listed in the _s_u_d_o_e_r_s file tries to - run a command via ssuuddoo, mail is sent to the proper author­ - ities, as defined at configure time or in the _s_u_d_o_e_r_s file - (defaults to root). Note that the mail will not be sent - if an unauthorized user tries to run sudo with the --ll or - --vv flags. This allows users to determine for themselves - whether or not they are allowed to use ssuuddoo. + If ssuuddoo is run by root and the SUDO_USER environment variable is set, + ssuuddoo will use this value to determine who the actual user is. This can + be used by a user to log commands through sudo even when a root shell + has been invoked. It also allows the --ee option to remain useful even + when being run via a sudo-run script or program. Note however, that + the sudoers lookup is still done for root, not the user specified by + SUDO_USER. - If ssuuddoo is run by root and the SUDO_USER environment vari­ - able is set, ssuuddoo will use this value to determine who the - actual user is. This can be used by a user to log com­ - mands through sudo even when a root shell has been - invoked. It also allows the --ee flag to remain useful even - when being run via a sudo-run script or program. Note - however, that 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.6.9p17 Jun 21, 2008 1 +1.7.0 November 15, 2008 1 @@ -70,64 +70,64 @@ 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. + 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. OOPPTTIIOONNSS ssuuddoo accepts the following command line options: - -a 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 allowed by _/_e_t_c_/_l_o_g_i_n_._c_o_n_f. The system - administrator may specify a list of sudo-specific - authentication methods by adding an "auth-sudo" entry - in _/_e_t_c_/_l_o_g_i_n_._c_o_n_f. This option is only available on - systems that support BSD authentication. - - -b The --bb (_b_a_c_k_g_r_o_u_n_d) option tells ssuuddoo to run the given - command in the background. Note that if you use the - --bb option you cannot use shell job control to manipu­ - late the process. + -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. - -c The --cc (_c_l_a_s_s) option causes ssuuddoo to run the specified - command with resources limited by the specified login - class. The _c_l_a_s_s argument can be either a class name - as defined in /etc/login.conf, or a single '-' charac­ - ter. Specifying a _c_l_a_s_s of - indicates that the com­ - mand should be run restricted by the default login - capabilities for the user the command is run as. If - the _c_l_a_s_s argument specifies an existing user class, - the command must be run as root, or the ssuuddoo command - must be run from a shell that is already root. This - option is only available on systems with BSD login - classes. + -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 + allowed by _/_e_t_c_/_l_o_g_i_n_._c_o_n_f. The system administrator may + specify a list of sudo-specific authentication methods by + adding an "auth-sudo" entry in _/_e_t_c_/_l_o_g_i_n_._c_o_n_f. This + option is only available on systems that support BSD + authentication. - -E The --EE (_p_r_e_s_e_r_v_e _e_n_v_i_r_o_n_m_e_n_t) option will override the - _e_n_v___r_e_s_e_t option in _s_u_d_o_e_r_s(4)). It is only available - when 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). + -b The --bb (_b_a_c_k_g_r_o_u_n_d) option tells ssuuddoo to run the given + command in the background. Note that if you use the --bb + option you cannot use shell job control to manipulate the + process. - -e The --ee (_e_d_i_t) option indicates that, instead of run­ - ning 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 _s_u_d_o_e_r_s the following steps are taken: + -C _f_d Normally, ssuuddoo will close all open file descriptors other + than standard input, standard output and standard error. + The --CC (_c_l_o_s_e _f_r_o_m) option allows the user to specify a + starting point above the standard error (file descriptor + three). Values less than three are not permitted. This + option is only available if the administrator has enabled + the _c_l_o_s_e_f_r_o_m___o_v_e_r_r_i_d_e option in _s_u_d_o_e_r_s(4). - 1. Temporary copies are made of the files to be - edited with the owner set to the invoking user. + -c _c_l_a_s_s The --cc (_c_l_a_s_s) option causes ssuuddoo to run the specified + command with resources limited by the specified login + class. The _c_l_a_s_s argument can be either a class name as + defined in _/_e_t_c_/_l_o_g_i_n_._c_o_n_f, or a single '-' character. + Specifying a _c_l_a_s_s of - indicates that the command should + be run restricted by the default login capabilities for the + user the command is run as. If the _c_l_a_s_s argument + specifies an existing user class, the command must be run + as root, or the ssuuddoo command must be run from a shell that + is already root. This option is only available on systems + with BSD login classes. - 2. The editor specified by the VISUAL or EDITOR envi­ - ronment variables is run to edit the temporary - files. If neither VISUAL nor EDITOR are set, the - program listed in the _e_d_i_t_o_r _s_u_d_o_e_r_s variable is - used. + -E The --EE (_p_r_e_s_e_r_v_e _e_n_v_i_r_o_n_m_e_n_t) option will override the + _e_n_v___r_e_s_e_t option in _s_u_d_o_e_r_s(4)). It is only available when + 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.6.9p17 Jun 21, 2008 2 +1.7.0 November 15, 2008 2 @@ -136,64 +136,64 @@ OOPPTTIIOONNSS SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - 3. If they have been modified, the temporary files - are copied back to their original location and the - temporary versions are removed. + 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 + _s_u_d_o_e_r_s the following steps are taken: - If the specified file does not exist, it will be cre­ - ated. Note that unlike most commands run by ssuuddoo, the - editor is run with the invoking user's environment - unmodified. If, for some reason, ssuuddoo is unable to - update a file with its edited version, the user will - receive a warning and the edited copy will remain in a - temporary file. + 1. Temporary copies are made of the files to be edited + with the owner set to the invoking user. - -H The --HH (_H_O_M_E) option sets the HOME environment vari­ - able to the homedir of the target user (root by - default) as specified in _p_a_s_s_w_d(4). By default, ssuuddoo - does not modify HOME (see _s_e_t___h_o_m_e and _a_l_w_a_y_s___s_e_t___h_o_m_e - in _s_u_d_o_e_r_s(4)). + 2. The editor specified by the SUDO_EDITOR, VISUAL or + EDITOR environment variables is run to edit the + temporary files. If none of SUDO_EDITOR, VISUAL or + EDITOR are set, the first program listed in the _e_d_i_t_o_r + _s_u_d_o_e_r_s variable is used. - -h The --hh (_h_e_l_p) option causes ssuuddoo to print a usage mes­ - sage and exit. + 3. If they have been modified, the temporary files are + copied back to their original location and the + temporary versions are removed. - -i The --ii (_s_i_m_u_l_a_t_e _i_n_i_t_i_a_l _l_o_g_i_n) option runs the shell - specified in the _p_a_s_s_w_d(4) entry of the user that the - command is being run as. The command name argument - given to the shell begins with a `-' to tell the shell - to run as a login shell. ssuuddoo attempts to change to - that user's home directory before running the shell. - It also initializes the environment, leaving _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, and unsetting all other environment variables. - Note that because the shell to use is determined - before the _s_u_d_o_e_r_s file is parsed, a _r_u_n_a_s___d_e_f_a_u_l_t - setting in _s_u_d_o_e_r_s will specify the user to run the - shell as but will not affect which shell is actually - run. + If the specified file does not exist, it will be created. + Note that unlike most commands run by ssuuddoo, the editor is + run with the invoking user's environment unmodified. If, + for some reason, ssuuddoo is unable to update a file with its + edited version, the user will receive a warning and the + edited copy will remain in a temporary file. - -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. + -g _g_r_o_u_p Normally, ssuuddoo sets the primary group to the one specified + by the passwd database for the user the command is being + run as (by default, root). The --gg (_g_r_o_u_p) option causes + ssuuddoo to run the specified command with the primary group + set to _g_r_o_u_p. To specify a _g_i_d instead of a _g_r_o_u_p _n_a_m_e, + use _#_g_i_d. When running commands as a _g_i_d, many shells + require that the '#' be escaped with a backslash ('\'). If + no --uu option is specified, the command will be run as the + invoking user (not root). In either case, the primary + group will be set to _g_r_o_u_p. - -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. + -H The --HH (_H_O_M_E) option sets the HOME environment variable to + the homedir of the target user (root by default) as + specified in _p_a_s_s_w_d(4). By default, ssuuddoo does not modify + HOME (see _s_e_t___h_o_m_e and _a_l_w_a_y_s___s_e_t___h_o_m_e in _s_u_d_o_e_r_s(4)). - -L The --LL (_l_i_s_t defaults) option will list out the param­ - eters that may be set in a _D_e_f_a_u_l_t_s line along with a - short description for each. This option is useful in - conjunction with _g_r_e_p(1). + -h The --hh (_h_e_l_p) option causes ssuuddoo to print a usage message + and exit. - -l The --ll (_l_i_s_t) option will list out the allowed (and - forbidden) commands for the invoking user on the + -i [command] + The --ii (_s_i_m_u_l_a_t_e _i_n_i_t_i_a_l _l_o_g_i_n) option runs the shell + specified in the _p_a_s_s_w_d(4) entry of the target user as a + login shell. This means that login-specific resource files + such as .profile or .login will be read by the shell. If a + command is specified, it is passed to the shell for + 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.6.9p17 Jun 21, 2008 3 +1.7.0 November 15, 2008 3 @@ -202,130 +202,130 @@ SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - current host. + _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. - -P The --PP (_p_r_e_s_e_r_v_e _g_r_o_u_p _v_e_c_t_o_r) option causes ssuuddoo to - preserve the invoking user's group vector unaltered. - By default, ssuuddoo will initialize the group vector to - the list of groups the target user is in. The real - and effective group IDs, however, are still set to - match the target user. + -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. - -p The --pp (_p_r_o_m_p_t) option allows you to override the - default password prompt and use a custom one. The - following percent (`%') escapes are supported: + -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. - %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) + -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 + description for each. This option is useful in conjunction + with _g_r_e_p(1). - %h expanded to the local hostname without the domain - name + -l[l] [_c_o_m_m_a_n_d] + If no _c_o_m_m_a_n_d is specified, the --ll (_l_i_s_t) option will list + the allowed (and forbidden) commands for the invoking user + (or the user specified by the --UU option) on the current + host. If a _c_o_m_m_a_n_d is specified and is permitted by + _s_u_d_o_e_r_s, the fully-qualified path to the command is + displayed along with any command line arguments. If + _c_o_m_m_a_n_d is specified but not allowed, ssuuddoo will exit with a + status value of 1. If the --ll option is specified with an ll + argument (i.e. --llll), or if --ll is specified multiple times, + a longer list format is used. - %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) + -n The --nn (_n_o_n_-_i_n_t_e_r_a_c_t_i_v_e) option prevents ssuuddoo from + prompting the user for a password. If a password is + required for the command to run, ssuuddoo will display an error + messages and exit. - %U expanded to the login name of the user the command - will be run as (defaults to root) + -P The --PP (_p_r_e_s_e_r_v_e _g_r_o_u_p _v_e_c_t_o_r) option causes ssuuddoo to + preserve the invoking user's group vector unaltered. By + default, ssuuddoo will initialize the group vector to the list + of groups the target user is in. The real and effective + group IDs, however, are still set to match the target user. - %u expanded to the invoking user's login name + -p _p_r_o_m_p_t The --pp (_p_r_o_m_p_t) option allows you to override the default + password prompt and use a custom one. The following + percent (`%') escapes are supported: - %% two consecutive % characters are collapsed into a - single % character + %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) - -S The --SS (_s_t_d_i_n) option causes ssuuddoo to read the password - from the standard input instead of the terminal - device. + %h expanded to the local hostname without the domain name - -s The --ss (_s_h_e_l_l) option runs the shell specified by the - _S_H_E_L_L environment variable if it is set or the shell - as specified in _p_a_s_s_w_d(4). + %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 - -u The --uu (_u_s_e_r) option causes ssuuddoo to run the specified - command as a user other than _r_o_o_t. To specify a _u_i_d - instead of a _u_s_e_r_n_a_m_e, use _#_u_i_d. When running com­ - mands as a _u_i_d, many shells require that the '#' be - escaped with a backslash ('\'). Note that if the _t_a_r_­ - _g_e_t_p_w Defaults option is set (see _s_u_d_o_e_r_s(4)) it is - not possible to run commands with a uid not listed in - the password database. - -V The --VV (_v_e_r_s_i_o_n) option causes ssuuddoo to print the ver­ - sion number and exit. If the invoking user is already - root the --VV option will print out a list of the - defaults ssuuddoo was compiled with as well as the - machine's local network addresses. +1.7.0 November 15, 2008 4 -1.6.9p17 Jun 21, 2008 4 +SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + _s_u_d_o_e_r_s) + %U expanded to the login name of the user the command will + be run as (defaults to root) - -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 pass­ - word 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. + %u expanded to the invoking user's login name - -- The ---- flag indicates that ssuuddoo should stop processing - command line arguments. It is most useful in conjunc­ - tion with the --ss flag. + %% two consecutive % characters are collapsed into a + single % character - 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 variables with one - important exception. If the _s_e_t_e_n_v option is set in _s_u_d_o_­ - _e_r_s, the command to be run has the SETENV tag set or the - command matched is ALL, the user may set variables that - would overwise be forbidden. See _s_u_d_o_e_r_s(4) for more - information. + The prompt specified by the --pp option will override the + system password prompt on systems that support PAM unless + the _p_a_s_s_p_r_o_m_p_t___o_v_e_r_r_i_d_e flag is disabled in _s_u_d_o_e_r_s. -RREETTUURRNN VVAALLUUEESS - Upon successful execution of a program, the return value - from ssuuddoo will simply be the return value of the program - that was executed. - - Otherwise, ssuuddoo quits with an exit value of 1 if there is - a configuration/permission problem or if ssuuddoo cannot exe­ - cute the given command. In the latter case the error - string is printed to stderr. If ssuuddoo cannot _s_t_a_t(2) one - or more entries in the user's PATH an error is printed on - stderr. (If the directory does not exist or if it is not - really a directory, the entry is ignored and no error is - printed.) This should not happen under normal circum­ - stances. The most common reason for _s_t_a_t(2) to return - "permission denied" is if you are running an automounter - and one of the directories in your PATH is on a machine - that is currently unreachable. + -S The --SS (_s_t_d_i_n) option causes ssuuddoo to read the password from + the standard input instead of the terminal device. -SSEECCUURRIITTYY NNOOTTEESS - ssuuddoo tries to be safe when executing external commands. + -s [command] + The --ss (_s_h_e_l_l) option runs the shell specified by the _S_H_E_L_L + environment variable if it is set or the shell as specified + in _p_a_s_s_w_d(4). If a command is specified, it is passed to + the shell for execution. Otherwise, an interactive shell + is executed. + + -U _u_s_e_r The --UU (_o_t_h_e_r _u_s_e_r) option is used in conjunction with the + --ll option to specify the user whose privileges should be + listed. Only root or a user with ssuuddoo ALL on the current + host may use this option. - There are two distinct ways to deal with environment vari­ - ables. By default, the _e_n_v___r_e_s_e_t _s_u_d_o_e_r_s option is - enabled. This causes commands to be executed with a mini­ - mal environment containing TERM, PATH, HOME, SHELL, LOG­ - NAME, USER and USERNAME in addition to variables from the - invoking process permitted by the _e_n_v___c_h_e_c_k and _e_n_v___k_e_e_p - _s_u_d_o_e_r_s options. There is effectively a whitelist for - environment variables. + -u _u_s_e_r The --uu (_u_s_e_r) option causes ssuuddoo to run the specified + command as a user other than _r_o_o_t. To specify a _u_i_d + instead of a _u_s_e_r _n_a_m_e, use _#_u_i_d. When running commands as + a _u_i_d, many shells require that the '#' be escaped with a + backslash ('\'). Note that if the _t_a_r_g_e_t_p_w Defaults option + is set (see _s_u_d_o_e_r_s(4)) it is not possible to run commands + with a uid not listed in the password database. - If, however, the _e_n_v___r_e_s_e_t option is disabled in _s_u_d_o_e_r_s, - any variables not explicitly denied by the _e_n_v___c_h_e_c_k and - _e_n_v___d_e_l_e_t_e options are inherited from the invoking + -V The --VV (_v_e_r_s_i_o_n) option causes ssuuddoo to print the version + number and exit. If the invoking user is already root the + --VV option will print out a list of the defaults ssuuddoo was + compiled with as well as the machine's local network + addresses. + -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. -1.6.9p17 Jun 21, 2008 5 + Environment variables to be set for the command may also be passed on + + + +1.7.0 November 15, 2008 5 @@ -334,64 +334,64 @@ SSEECCUURRIITTYY NNOOTTEESS SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - process. In this case, _e_n_v___c_h_e_c_k and _e_n_v___d_e_l_e_t_e behave - like a blacklist. Since it is not possible to blacklist - all potentially dangerous environment variables, use of - the default _e_n_v___r_e_s_e_t behavior is encouraged. - - In all cases, environment variables with a value beginning - with () are removed as they could be interpreted as bbaasshh - functions. The list of environment variables that ssuuddoo - allows or denies is contained in the 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 oth­ - ers. These type of variables are removed from the envi­ - ronment 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 com­ - mand 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 program - that ssuuddoo executes. - - ssuuddoo will check the ownership of its timestamp directory - (_/_v_a_r_/_r_u_n_/_s_u_d_o by default) and ignore the directory's con­ - tents if it is not owned by root or if it is writable by a - user other than root. On systems that allow non-root - users to give away files via _c_h_o_w_n(2), if the timestamp - directory is located in a directory writable by anyone - (e.g., _/_t_m_p), it is possible for a user to create the - timestamp directory before ssuuddoo is run. However, because - ssuuddoo checks the ownership and mode of the directory and - its contents, the only damage that can be done is to - "hide" files by putting them in the timestamp dir. This - is unlikely to happen since once the timestamp dir is - owned by root and inaccessible by any other user, the user - placing files there would be unable to get them back out. - To get around this issue you can use a directory that is - not world-writable for the timestamps (_/_v_a_r_/_a_d_m_/_s_u_d_o for - instance) or create _/_v_a_r_/_r_u_n_/_s_u_d_o with the appropriate - owner (root) and permissions (0700) in the system startup - files. - - ssuuddoo will not honor timestamps set far in the future. - Timestamps with a date greater than current_time + 2 * - TIMEOUT will be ignored and sudo will log and complain. - This is done to keep a user from creating his/her own - timestamp with a bogus date on systems that allow users to - give away files. + 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 + variables with one important exception. If the _s_e_t_e_n_v option is set in + _s_u_d_o_e_r_s, the command to be run has the SETENV tag set or the command + matched is ALL, the user may set variables that would overwise be + forbidden. See _s_u_d_o_e_r_s(4) for more information. + +RREETTUURRNN VVAALLUUEESS + Upon successful execution of a program, the exit status from ssuuddoo will + simply be the exit status of the program that was executed. + + Otherwise, ssuuddoo quits with an exit value of 1 if there is a + configuration/permission problem or if ssuuddoo cannot execute the given + command. In the latter case the error string is printed to stderr. If + ssuuddoo cannot _s_t_a_t(2) one or more entries in the user's PATH an error is + printed on stderr. (If the directory does not exist or if it is not + really a directory, the entry is ignored and no error is printed.) + This should not happen under normal circumstances. The most common + reason for _s_t_a_t(2) to return "permission denied" is if you are running + an automounter and one of the directories in your PATH is on a machine + that is currently unreachable. + +SSEECCUURRIITTYY NNOOTTEESS + ssuuddoo tries to be safe when executing external commands. + There are two distinct ways to deal with environment variables. By + default, the _e_n_v___r_e_s_e_t _s_u_d_o_e_r_s option is enabled. This causes commands + to be executed with a minimal environment containing TERM, PATH, HOME, + SHELL, LOGNAME, USER and USERNAME in addition to variables from the + invoking process permitted by the _e_n_v___c_h_e_c_k and _e_n_v___k_e_e_p _s_u_d_o_e_r_s + options. There is effectively a whitelist for environment variables. + If, however, the _e_n_v___r_e_s_e_t option is disabled in _s_u_d_o_e_r_s, any variables + not explicitly denied by the _e_n_v___c_h_e_c_k and _e_n_v___d_e_l_e_t_e options are + inherited from the invoking process. In this case, _e_n_v___c_h_e_c_k and + _e_n_v___d_e_l_e_t_e behave like a blacklist. Since it is not possible to + blacklist all potentially dangerous environment variables, use of the + default _e_n_v___r_e_s_e_t behavior is encouraged. + In all cases, environment variables with a value beginning with () are + removed as they could be interpreted as bbaasshh functions. The list of + environment variables that ssuuddoo allows or denies is contained in the + output of sudo -V when run as root. -1.6.9p17 Jun 21, 2008 6 + 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 @@ -400,83 +400,112 @@ SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - Please note that ssuuddoo will normally only log the command - it explicitly runs. If a user runs a command such as sudo - su or sudo sh, subsequent commands run from that shell - will _n_o_t be logged, nor will ssuuddoo's access control affect - them. The same is true for commands that offer shell - escapes (including most editors). Because of this, care - must be taken when giving users access to commands via - ssuuddoo to verify that the command does not inadvertently - give the user an effective root shell. For more informa­ - tion, please see the PREVENTING SHELL ESCAPES section in - _s_u_d_o_e_r_s(4). + 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 + program that ssuuddoo executes. + + ssuuddoo will check the ownership of its timestamp directory (_/_v_a_r_/_r_u_n_/_s_u_d_o + by default) and ignore the directory's contents if it is not owned by + root or if it is writable by a user other than root. On systems that + allow non-root users to give away files via _c_h_o_w_n(2), if the timestamp + directory is located in a directory writable by anyone (e.g., _/_t_m_p), it + is possible for a user to create the timestamp directory before ssuuddoo is + run. However, because ssuuddoo checks the ownership and mode of the + directory and its contents, the only damage that can be done is to + "hide" files by putting them in the timestamp dir. This is unlikely to + happen since once the timestamp dir is owned by root and inaccessible + by any other user, the user placing files there would be unable to get + them back out. To get around this issue you can use a directory that + is not world-writable for the timestamps (_/_v_a_r_/_a_d_m_/_s_u_d_o for instance) + or create _/_v_a_r_/_r_u_n_/_s_u_d_o with the appropriate owner (root) and + permissions (0700) in the system startup files. + + ssuuddoo will not honor timestamps set far in the future. Timestamps with + a date greater than current_time + 2 * TIMEOUT will be ignored and sudo + will log and complain. This is done to keep a user from creating + his/her own timestamp with a bogus date on systems that allow users to + give away files. + + Please note that ssuuddoo will normally only log the command it explicitly + runs. If a user runs a command such as sudo su or sudo sh, subsequent + commands run from that shell will _n_o_t be logged, nor will ssuuddoo's access + control affect them. The same is true for commands that offer shell + escapes (including most editors). Because of this, care must be taken + when giving users access to commands via ssuuddoo to verify that the + command does not inadvertently give the user an effective root shell. + For more information, please see the PREVENTING SHELL ESCAPES section + in _s_u_d_o_e_r_s(4). EENNVVIIRROONNMMEENNTT ssuuddoo utilizes the following environment variables: - EDITOR Default editor to use in --ee (sudoedit) - mode if VISUAL is not set + EDITOR Default editor to use in --ee (sudoedit) mode if neither + SUDO_EDITOR nor VISUAL is set - HOME In --ss or --HH mode (or if sudo was config­ - ured with the --enable-shell-sets-home - option), set to homedir of the target user + HOME In --ss or --HH mode (or if sudo was configured with the + --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. + 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 + SHELL Used to determine shell to run with -s option - SUDO_PROMPT Used as the default password prompt + SUDO_ASKPASS Specifies the path to a helper program used to read the + password if no terminal is available or if the -A - SUDO_COMMAND Set to the command run by sudo - SUDO_USER Set to the login of the user who invoked - sudo - SUDO_UID Set to the uid of the user who invoked - sudo +1.7.0 November 15, 2008 7 - SUDO_GID Set to the gid of the user who invoked - sudo - SUDO_PS1 If set, PS1 will be set to its value - USER Set to the target user (root unless the --uu - option is specified) - VISUAL Default editor to use in --ee (sudoedit) - mode -FFIILLEESS - _/_e_t_c_/_s_u_d_o_e_r_s List of who can run what +SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - _/_v_a_r_/_r_u_n_/_s_u_d_o Directory containing timestamps + option is specified. + SUDO_COMMAND Set to the command run by sudo + SUDO_EDITOR Default editor to use in --ee (sudoedit) mode -1.6.9p17 Jun 21, 2008 7 + SUDO_GID Set to the group ID of the user who invoked sudo + SUDO_PROMPT Used as the default password prompt + SUDO_PS1 If set, PS1 will be set to its value for the program + being run + SUDO_UID Set to the user ID of the user who invoked sudo + SUDO_USER Set to the login of the user who invoked sudo -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + USER Set to the target user (root unless the --uu option is + specified) + VISUAL Default editor to use in --ee (sudoedit) mode if + SUDO_EDITOR is not set + +FFIILLEESS + _/_e_t_c_/_s_u_d_o_e_r_s List of who can run what + + _/_v_a_r_/_r_u_n_/_s_u_d_o Directory containing timestamps + + _/_e_t_c_/_e_n_v_i_r_o_n_m_e_n_t Initial environment for --ii mode on Linux and + AIX EEXXAAMMPPLLEESS - Note: the following examples assume suitable _s_u_d_o_e_r_s(4) - entries. + Note: the following examples assume suitable _s_u_d_o_e_r_s(4) entries. 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 yazza on a machine where the file + system holding ~yazza is not exported as root: $ sudo -u yazza ls ~yazza @@ -488,107 +517,78 @@ EEXXAAMMPPLLEESS $ 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. + 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" -SSEEEE AALLSSOO - _g_r_e_p(1), _s_u(1), _s_t_a_t(2), _l_o_g_i_n___c_a_p(3), _p_a_s_s_w_d(4), - _s_u_d_o_e_r_s(5), _v_i_s_u_d_o(1m) -AAUUTTHHOORRSS - Many people have worked on ssuuddoo over the years; this ver­ - sion consists of code written primarily by: +1.7.0 November 15, 2008 8 - Todd C. Miller - Chris Jepeway - See the HISTORY file in the ssuuddoo distribution or visit - http://www.sudo.ws/sudo/history.html for a short history - of ssuuddoo. -CCAAVVEEAATTSS - There is no easy way to prevent a user from gaining a root - shell if that user is allowed to run arbitrary commands - via ssuuddoo. Also, many programs (such as editors) allow the - user to run commands via shell escapes, thus avoiding - ssuuddoo's checks. However, on most systems it is possible to - prevent shell escapes with ssuuddoo's _n_o_e_x_e_c functionality. - See the _s_u_d_o_e_r_s(4) manual for details. - It is not meaningful to run the cd command directly via - sudo, e.g., +SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) -1.6.9p17 Jun 21, 2008 8 + $ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE" +SSEEEE AALLSSOO + _g_r_e_p(1), _s_u(1), _s_t_a_t(2), _l_o_g_i_n___c_a_p(3), _p_a_s_s_w_d(4), _s_u_d_o_e_r_s(5), + _v_i_s_u_d_o(1m) +AAUUTTHHOORRSS + Many people have worked on ssuuddoo over the years; this version consists + of code written primarily by: + Todd C. Miller + See the HISTORY file in the ssuuddoo distribution or visit + http://www.sudo.ws/sudo/history.html for a short history of ssuuddoo. -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) +CCAAVVEEAATTSS + There is no easy way to prevent a user from gaining a root shell if + that user is allowed to run arbitrary commands via ssuuddoo. Also, many + programs (such as editors) allow the user to run commands via shell + escapes, thus avoiding ssuuddoo's checks. However, on most systems it is + possible to prevent shell escapes with ssuuddoo's _n_o_e_x_e_c functionality. + See the _s_u_d_o_e_r_s(4) manual for details. + It is not meaningful to run the cd command directly via sudo, e.g., $ sudo cd /usr/local/protected - since when the command exits the parent process (your - shell) will still be the same. Please see the EXAMPLES - section for more information. + since when the command exits the parent process (your shell) will still + be the same. Please see the EXAMPLES section for more information. - If users have sudo ALL there is nothing to prevent them - from creating their own program that gives them a root - shell regardless of any '!' elements in the user specifi­ - cation. + If users have sudo ALL there is nothing to prevent them from creating + their own program that gives them a root shell regardless of any '!' + elements in the user specification. - Running shell scripts via ssuuddoo can expose the same kernel - bugs that make setuid shell scripts unsafe on some operat­ - ing systems (if your OS has a /dev/fd/ directory, setuid - shell scripts are generally safe). + Running shell scripts via ssuuddoo can expose the same kernel bugs that + make setuid shell scripts unsafe on some operating systems (if your OS + has a /dev/fd/ directory, setuid shell scripts are generally safe). BBUUGGSS - If you feel you have found a bug in ssuuddoo, please submit a - bug report at http://www.sudo.ws/sudo/bugs/ + If you feel you have found a bug in ssuuddoo, please submit a bug report at + http://www.sudo.ws/sudo/bugs/ SSUUPPPPOORRTT - Limited free support is available via the sudo-users mail­ - ing list, see http://www.sudo.ws/mail­ - man/listinfo/sudo-users to subscribe or search the - archives. + Limited free support is available via the sudo-users mailing list, see + http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search + the archives. DDIISSCCLLAAIIMMEERR - ssuuddoo is provided ``AS IS'' and any express or implied war­ - ranties, including, but not limited to, the implied war­ - ranties of merchantability and fitness for a particular - purpose are disclaimed. See the LICENSE file distributed - with ssuuddoo or http://www.sudo.ws/sudo/license.html for com­ - plete details. - - - - - - - - - - - - - - - - - - - - + ssuuddoo is provided ``AS IS'' and any express or implied warranties, + including, but not limited to, the implied warranties of + merchantability and fitness for a particular purpose are disclaimed. + See the LICENSE file distributed with ssuuddoo or + http://www.sudo.ws/sudo/license.html for complete details. -1.6.9p17 Jun 21, 2008 9 +1.7.0 November 15, 2008 9 diff --git a/sudo.h b/sudo.h index 889cd4a..ac5fdbd 100644 --- a/sudo.h +++ b/sudo.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 1993-1996,1998-2007 Todd C. Miller + * Copyright (c) 1993-1996, 1998-2005, 2007-2008 + * 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 @@ -17,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.209.2.14 2008/02/09 14:44:48 millert Exp $ + * $Sudo: sudo.h,v 1.269 2008/11/25 17:01:34 millert Exp $ */ #ifndef _SUDO_SUDO_H @@ -27,7 +28,10 @@ #include #include "compat.h" #include "defaults.h" +#include "error.h" +#include "list.h" #include "logging.h" +#include "sudo_nss.h" /* * Info pertaining to the invoking user. @@ -35,28 +39,31 @@ struct sudo_user { struct passwd *pw; struct passwd *_runas_pw; + struct group *_runas_gr; struct stat *cmnd_stat; char *path; char *shell; char *tty; char *ttypath; - char cwd[PATH_MAX]; char *host; char *shost; - char **runas; char *prompt; char *cmnd; char *cmnd_args; char *cmnd_base; char *cmnd_safe; char *class_name; - int ngroups; + char *krb5_ccname; + char *display; + char *askpass; + int ngroups; GETGROUPS_T *groups; struct list_member *env_vars; #ifdef HAVE_SELINUX char *role; char *type; #endif + char cwd[PATH_MAX]; }; /* @@ -68,12 +75,9 @@ struct sudo_user { #define VALIDATE_OK 0x002 #define VALIDATE_NOT_OK 0x004 #define FLAG_CHECK_USER 0x010 -#define FLAG_NOPASS 0x020 -#define FLAG_NO_USER 0x040 -#define FLAG_NO_HOST 0x080 -#define FLAG_NO_CHECK 0x100 -#define FLAG_NOEXEC 0x200 -#define FLAG_SETENV 0x400 +#define FLAG_NO_USER 0x020 +#define FLAG_NO_HOST 0x040 +#define FLAG_NO_CHECK 0x080 /* * Pseudo-boolean values @@ -82,12 +86,6 @@ struct sudo_user { #define TRUE 1 #undef FALSE #define FALSE 0 -#undef IMPLIED -#define IMPLIED 2 -#undef NOMATCH -#define NOMATCH -1 -#undef UNSPEC -#define UNSPEC -2 /* * find_path()/load_cmnd() return values @@ -99,22 +97,27 @@ struct sudo_user { /* * Various modes sudo can be in (based on arguments) in hex */ -#define MODE_RUN 0x0001 -#define MODE_EDIT 0x0002 -#define MODE_VALIDATE 0x0004 -#define MODE_INVALIDATE 0x0008 -#define MODE_KILL 0x0010 -#define MODE_VERSION 0x0020 -#define MODE_HELP 0x0040 -#define MODE_LIST 0x0080 -#define MODE_LISTDEFS 0x0100 -#define MODE_BACKGROUND 0x0200 -#define MODE_SHELL 0x0400 -#define MODE_LOGIN_SHELL 0x0800 -#define MODE_IMPLIED_SHELL 0x1000 -#define MODE_RESET_HOME 0x2000 -#define MODE_PRESERVE_GROUPS 0x4000 -#define MODE_PRESERVE_ENV 0x8000 +#define MODE_RUN 0x00000001 +#define MODE_EDIT 0x00000002 +#define MODE_VALIDATE 0x00000004 +#define MODE_INVALIDATE 0x00000008 +#define MODE_KILL 0x00000010 +#define MODE_VERSION 0x00000020 +#define MODE_HELP 0x00000040 +#define MODE_LIST 0x00000080 +#define MODE_CHECK 0x00000100 +#define MODE_LISTDEFS 0x00000200 +#define MODE_MASK 0x0000ffff + +/* Mode flags */ +#define MODE_BACKGROUND 0x00010000 +#define MODE_SHELL 0x00020000 +#define MODE_LOGIN_SHELL 0x00040000 +#define MODE_IMPLIED_SHELL 0x00080000 +#define MODE_RESET_HOME 0x00100000 +#define MODE_PRESERVE_GROUPS 0x00200000 +#define MODE_PRESERVE_ENV 0x00400000 +#define MODE_NONINTERACTIVE 0x00800000 /* * Used with set_perms() @@ -141,7 +144,6 @@ struct sudo_user { #define user_tty (sudo_user.tty) #define user_ttypath (sudo_user.ttypath) #define user_cwd (sudo_user.cwd) -#define user_runas (sudo_user.runas) #define user_cmnd (sudo_user.cmnd) #define user_args (sudo_user.cmnd_args) #define user_base (sudo_user.cmnd_base) @@ -150,9 +152,13 @@ struct sudo_user { #define user_prompt (sudo_user.prompt) #define user_host (sudo_user.host) #define user_shost (sudo_user.shost) +#define user_ccname (sudo_user.krb5_ccname) +#define user_display (sudo_user.display) +#define user_askpass (sudo_user.askpass) #define safe_cmnd (sudo_user.cmnd_safe) #define login_class (sudo_user.class_name) #define runas_pw (sudo_user._runas_pw) +#define runas_gr (sudo_user._runas_gr) #define user_role (sudo_user.role) #define user_type (sudo_user.type) @@ -176,7 +182,9 @@ struct sudo_user { */ #define TGP_ECHO 0x01 /* leave echo on when reading passwd */ #define TGP_STDIN 0x02 /* read from stdin, not /dev/tty */ +#define TGP_ASKPASS 0x04 /* read from askpass helper program */ +struct lbuf; struct passwd; struct timespec; struct timeval; @@ -224,7 +232,7 @@ size_t strlcat __P((char *, const char *, size_t)); size_t strlcpy __P((char *, const char *, size_t)); #endif #ifndef HAVE_MEMRCHR -VOID *memrchr __P((const VOID *, int, size_t)); +void *memrchr __P((const void *, int, size_t)); #endif #ifndef HAVE_MKSTEMP int mkstemp __P((char *)); @@ -232,13 +240,29 @@ int mkstemp __P((char *)); char *sudo_goodpath __P((const char *, struct stat *)); char *tgetpass __P((const char *, int, int)); int find_path __P((char *, char **, struct stat *, char *)); -void check_user __P((int)); +int tty_present __P((void)); +void check_user __P((int, int)); void verify_user __P((struct passwd *, char *)); -int sudoers_lookup __P((int)); #ifdef HAVE_LDAP -int sudo_ldap_check __P((int)); -void sudo_ldap_list_matches __P((void)); +int sudo_ldap_open __P((struct sudo_nss *)); +int sudo_ldap_close __P((struct sudo_nss *)); +int sudo_ldap_setdefs __P((struct sudo_nss *)); +int sudo_ldap_lookup __P((struct sudo_nss *, int, int)); +int sudo_ldap_parse __P((struct sudo_nss *)); +int sudo_ldap_display_cmnd __P((struct sudo_nss *, struct passwd *)); +int sudo_ldap_display_defaults __P((struct sudo_nss *, struct passwd *, struct lbuf *)); +int sudo_ldap_display_bound_defaults __P((struct sudo_nss *, struct passwd *, struct lbuf *)); +int sudo_ldap_display_privs __P((struct sudo_nss *, struct passwd *, struct lbuf *)); #endif +int sudo_file_open __P((struct sudo_nss *)); +int sudo_file_close __P((struct sudo_nss *)); +int sudo_file_setdefs __P((struct sudo_nss *)); +int sudo_file_lookup __P((struct sudo_nss *, int, int)); +int sudo_file_parse __P((struct sudo_nss *)); +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)); void remove_timestamp __P((int)); int check_secureware __P((char *)); @@ -246,40 +270,63 @@ void sia_attempt_auth __P((void)); void pam_attempt_auth __P((void)); int yyparse __P((void)); void pass_warn __P((FILE *)); -VOID *emalloc __P((size_t)); -VOID *emalloc2 __P((size_t, size_t)); -VOID *erealloc __P((VOID *, size_t)); -VOID *erealloc3 __P((VOID *, size_t, size_t)); +void *emalloc __P((size_t)); +void *emalloc2 __P((size_t, size_t)); +void *erealloc __P((void *, size_t)); +void *erealloc3 __P((void *, size_t, size_t)); char *estrdup __P((const char *)); int easprintf __P((char **, const char *, ...)) __printflike(2, 3); int evasprintf __P((char **, const char *, va_list)) __printflike(2, 0); -void efree __P((VOID *)); +void efree __P((void *)); void dump_defaults __P((void)); void dump_auth_methods __P((void)); void init_envtables __P((void)); +void read_env_file __P((const char *, int)); int lock_file __P((int, int)); int touch __P((int, char *, struct timespec *)); int user_is_exempt __P((void)); void set_fqdn __P((void)); -int set_runaspw __P((char *)); char *sudo_getepw __P((const struct passwd *)); int pam_prep_user __P((struct passwd *)); -void zero_bytes __P((volatile VOID *, size_t)); +void zero_bytes __P((volatile void *, size_t)); int gettime __P((struct timespec *)); +FILE *open_sudoers __P((const char *, 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)); +void sudo_endpwent __P((void)); +void sudo_setspent __P((void)); +void sudo_endspent __P((void)); +void cleanup __P((int)); +struct passwd *sudo_getpwnam __P((const char *)); +struct passwd *sudo_fakepwnam __P((const char *, gid_t)); +struct passwd *sudo_getpwuid __P((uid_t)); +struct group *sudo_getgrnam __P((const char *)); +struct group *sudo_fakegrnam __P((const char *)); +struct group *sudo_getgrgid __P((gid_t)); #ifdef HAVE_SELINUX -void selinux_exec __P((char *, char *, char **, char **, int)); +void selinux_exec __P((char *, char *, char **, int)); +#endif +#ifdef HAVE_GETUSERATTR +void aix_setlimits __P((char *)); #endif YY_DECL; /* Only provide extern declarations outside of sudo.c. */ #ifndef _SUDO_MAIN extern struct sudo_user sudo_user; -extern struct passwd *auth_pw; +extern struct passwd *auth_pw, *list_pw; -extern FILE *sudoers_fp; extern int tgetpass_flags; +extern int long_list; extern uid_t timestamp_uid; #endif #ifndef errno diff --git a/sudo.man.in b/sudo.man.in index 8d881c9..26d8a30 100644 --- a/sudo.man.in +++ b/sudo.man.in @@ -1,4 +1,4 @@ -.\" Copyright (c) 1994-1996, 1998-2005, 2007 +.\" Copyright (c) 1994-1996, 1998-2005, 2007-2008 .\" Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -18,8 +18,8 @@ .\" 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.29.2.27 2008/06/22 20:29:03 millert Exp $ -.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 +.\" $Sudo: sudo.man.in,v 1.53 2008/11/15 18:34:26 millert Exp $ +.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.05) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,11 +46,11 @@ .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. | will give a -.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to -.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' -.\" expand to `' in nroff, nothing in troff, for use with C<>. -.tr \(*W-|\(bv\*(Tr +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- @@ -69,22 +69,25 @@ . ds R" '' 'br\} .\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. -.if \nF \{\ +.ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} -.\" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.hy 0 -.if n .na +.el \{\ +. de IX +.. +.\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -150,26 +153,35 @@ .\" ======================================================================== .\" .IX Title "SUDO @mansectsu@" -.TH SUDO @mansectsu@ "Jun 21, 2008" "1.6.9p17" "MAINTENANCE COMMANDS" +.TH SUDO @mansectsu@ "November 15, 2008" "1.7.0" "MAINTENANCE COMMANDS" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh .SH "NAME" sudo, sudoedit \- execute a command as another user .SH "SYNOPSIS" .IX Header "SYNOPSIS" -\&\fBsudo\fR \fB\-h\fR | \fB\-K\fR | \fB\-k\fR | \fB\-L\fR | \fB\-l\fR | \fB\-V\fR | \fB\-v\fR +\&\fBsudo\fR [\fB\-n\fR] \fB\-h\fR | \fB\-K\fR | \fB\-k\fR | \fB\-L\fR | \fB\-V\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] .PP -\&\fBsudo\fR [\fB\-bEHPS\fR] +\&\fBsudo\fR [\fB\-AbEHnPS\fR] @BAMAN@[\fB\-a\fR\ \fIauth_type\fR] +[\fB\-C\fR\ \fIfd\fR] @LCMAN@[\fB\-c\fR\ \fIclass\fR|\fI\-\fR] -[\fB\-p\fR\ \fIprompt\fR] +[\fB\-g\fR\ \fIgroupname\fR|\fI#gid\fR] [\fB\-p\fR\ \fIprompt\fR] @SEMAN@[\fB\-r\fR\ \fIrole\fR] [\fB\-t\fR\ \fItype\fR] [\fB\-u\fR\ \fIusername\fR|\fI#uid\fR] -[\fB\s-1VAR\s0\fR=\fIvalue\fR] {\fB\-i\fR\ |\ \fB\-s\fR\ |\ \fIcommand\fR} +[\fB\s-1VAR\s0\fR=\fIvalue\fR] [\fB\-i\fR\ |\ \fB\-s\fR] [\fIcommand\fR] .PP -\&\fBsudoedit\fR [\fB\-S\fR] +\&\fBsudoedit\fR [\fB\-AnS\fR] @BAMAN@[\fB\-a\fR\ \fIauth_type\fR] +[\fB\-C\fR\ \fIfd\fR] @LCMAN@[\fB\-c\fR\ \fIclass\fR|\fI\-\fR] -[\fB\-p\fR\ \fIprompt\fR] [\fB\-u\fR\ \fIusername\fR|\fI#uid\fR] -file ... +[\fB\-g\fR\ \fIgroupname\fR|\fI#gid\fR] [\fB\-p\fR\ \fIprompt\fR] +[\fB\-u\fR\ \fIusername\fR|\fI#uid\fR] file ... .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fBsudo\fR allows a permitted user to execute a \fIcommand\fR as the @@ -190,17 +202,17 @@ When invoked as \fBsudoedit\fR, the \fB\-e\fR option (described below), is implied. .PP \&\fBsudo\fR determines who is an authorized user by consulting the file -\&\fI@sysconfdir@/sudoers\fR. By giving \fBsudo\fR the \fB\-v\fR flag, a user -can update the time stamp without running a \fIcommand\fR. The password -prompt itself will also time out if the user's password is not -entered within \f(CW\*(C`@password_timeout@\*(C'\fR minutes (unless overridden via -\&\fIsudoers\fR). +\&\fI@sysconfdir@/sudoers\fR. By running \fBsudo\fR with the \fB\-v\fR option, +a user can update the time stamp without running a \fIcommand\fR. The +password prompt itself will also time out if the user's password +is not entered within \f(CW\*(C`@password_timeout@\*(C'\fR minutes (unless overridden +via \fIsudoers\fR). .PP If a user who is not listed in the \fIsudoers\fR file tries to run a command via \fBsudo\fR, mail is sent to the proper authorities, as defined at configure time or in the \fIsudoers\fR file (defaults to \&\f(CW\*(C`@mailto@\*(C'\fR). Note that the mail will not be sent if an unauthorized -user tries to run sudo with the \fB\-l\fR or \fB\-v\fR flags. This allows +user tries to run sudo with the \fB\-l\fR or \fB\-v\fR option. This allows users to determine for themselves whether or not they are allowed to use \fBsudo\fR. .PP @@ -208,7 +220,7 @@ If \fBsudo\fR is run by root and the \f(CW\*(C`SUDO_USER\*(C'\fR environment var is set, \fBsudo\fR will use this value to determine who the actual user is. This can be used by a user to log commands through sudo even when a root shell has been invoked. It also allows the \fB\-e\fR -flag to remain useful even when being run via a sudo-run script or +option to remain useful even when being run via a sudo-run script or program. Note however, that the sudoers lookup is still done for root, not the user specified by \f(CW\*(C`SUDO_USER\*(C'\fR. .PP @@ -219,57 +231,75 @@ or via the \fIsudoers\fR file. .SH "OPTIONS" .IX Header "OPTIONS" \&\fBsudo\fR accepts the following command line options: -@BAMAN@.IP "\-a" 4 -@BAMAN@.IX Item "-a" +.IP "\-A" 12 +.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. +@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 @BAMAN@specified authentication type when validating the user, as allowed @BAMAN@by \fI/etc/login.conf\fR. The system administrator may specify a list -@BAMAN@of sudo-specific authentication methods by adding an \*(L"auth\-sudo\*(R" +@BAMAN@of sudo-specific authentication methods by adding an \*(L"auth-sudo\*(R" @BAMAN@entry in \fI/etc/login.conf\fR. This option is only available on systems @BAMAN@that support \s-1BSD\s0 authentication. -.IP "\-b" 4 +.IP "\-b" 12 .IX Item "-b" The \fB\-b\fR (\fIbackground\fR) option tells \fBsudo\fR to run the given command in the background. Note that if you use the \fB\-b\fR option you cannot use shell job control to manipulate the process. -@LCMAN@.IP "\-c" 4 -@LCMAN@.IX Item "-c" +.IP "\-C \fIfd\fR" 12 +.IX Item "-C fd" +Normally, \fBsudo\fR will close all open file descriptors other than +standard input, standard output and standard error. The \fB\-C\fR +(\fIclose from\fR) option allows the user to specify a starting point +above the standard error (file descriptor three). Values less than +three are not permitted. This option is only available if the +administrator has enabled the \fIclosefrom_override\fR option in +\&\fIsudoers\fR\|(@mansectform@). +@LCMAN@.IP "\-c \fIclass\fR" 12 +@LCMAN@.IX Item "-c class" @LCMAN@The \fB\-c\fR (\fIclass\fR) option causes \fBsudo\fR to run the specified command @LCMAN@with resources limited by the specified login class. The \fIclass\fR -@LCMAN@argument can be either a class name as defined in \f(CW\*(C`/etc/login.conf\*(C'\fR, +@LCMAN@argument can be either a class name as defined in \fI/etc/login.conf\fR, @LCMAN@or a single '\-' character. Specifying a \fIclass\fR of \f(CW\*(C`\-\*(C'\fR indicates @LCMAN@that the command should be run restricted by the default login @LCMAN@capabilities for the user the command is run as. If the \fIclass\fR @LCMAN@argument specifies an existing user class, the command must be run @LCMAN@as root, or the \fBsudo\fR command must be run from a shell that is already @LCMAN@root. This option is only available on systems with \s-1BSD\s0 login classes. -.IP "\-E" 4 +.IP "\-E" 12 .IX Item "-E" The \fB\-E\fR (\fIpreserve\fR \fIenvironment\fR) option will override the \&\fIenv_reset\fR option in \fIsudoers\fR\|(@mansectform@)). It is only available when either the matching command has the \f(CW\*(C`SETENV\*(C'\fR tag or the \fIsetenv\fR option is set in \fIsudoers\fR\|(@mansectform@). -.IP "\-e" 4 +.IP "\-e" 12 .IX Item "-e" The \fB\-e\fR (\fIedit\fR) option indicates that, instead of running a command, the user wishes to edit one or more files. In lieu of a command, the string \*(L"sudoedit\*(R" is used when consulting the \fIsudoers\fR file. If the user is authorized by \fIsudoers\fR the following steps are taken: -.RS 4 +.RS 12 .IP "1." 4 Temporary copies are made of the files to be edited with the owner set to the invoking user. .IP "2." 4 -The editor specified by the \f(CW\*(C`VISUAL\*(C'\fR or \f(CW\*(C`EDITOR\*(C'\fR environment -variables is run to edit the temporary files. If neither \f(CW\*(C`VISUAL\*(C'\fR -nor \f(CW\*(C`EDITOR\*(C'\fR are set, the program listed in the \fIeditor\fR \fIsudoers\fR -variable is used. +The editor specified by the \f(CW\*(C`SUDO_EDITOR\*(C'\fR, \f(CW\*(C`VISUAL\*(C'\fR or \f(CW\*(C`EDITOR\*(C'\fR +environment variables is run to edit the temporary files. If none +of \f(CW\*(C`SUDO_EDITOR\*(C'\fR, \f(CW\*(C`VISUAL\*(C'\fR or \f(CW\*(C`EDITOR\*(C'\fR are set, the first program +listed in the \fIeditor\fR \fIsudoers\fR variable is used. .IP "3." 4 If they have been modified, the temporary files are copied back to their original location and the temporary versions are removed. .RE -.RS 4 +.RS 12 .Sp If the specified file does not exist, it will be created. Note that unlike most commands run by \fBsudo\fR, the editor is run with @@ -278,63 +308,85 @@ the invoking user's environment unmodified. If, for some reason, user will receive a warning and the edited copy will remain in a temporary file. .RE -.IP "\-H" 4 +.IP "\-g \fIgroup\fR" 12 +.IX Item "-g group" +Normally, \fBsudo\fR sets the primary group to the one specified by +the passwd database for the user the command is being run as (by +default, root). The \fB\-g\fR (\fIgroup\fR) option causes \fBsudo\fR to run +the specified command with the primary group set to \fIgroup\fR. To +specify a \fIgid\fR instead of a \fIgroup name\fR, use \fI#gid\fR. When +running commands as a \fIgid\fR, many shells require that the '#' be +escaped with a backslash ('\e'). If no \fB\-u\fR option is specified, +the command will be run as the invoking user (not root). In either +case, the primary group will be set to \fIgroup\fR. +.IP "\-H" 12 .IX Item "-H" The \fB\-H\fR (\fI\s-1HOME\s0\fR) option sets the \f(CW\*(C`HOME\*(C'\fR environment variable to the homedir of the target user (root by default) as specified in \fIpasswd\fR\|(@mansectform@). By default, \fBsudo\fR does not modify \f(CW\*(C`HOME\*(C'\fR (see \fIset_home\fR and \fIalways_set_home\fR in \fIsudoers\fR\|(@mansectform@)). -.IP "\-h" 4 +.IP "\-h" 12 .IX Item "-h" The \fB\-h\fR (\fIhelp\fR) option causes \fBsudo\fR to print a usage message and exit. -.IP "\-i" 4 -.IX Item "-i" +.IP "\-i [command]" 12 +.IX Item "-i [command]" The \fB\-i\fR (\fIsimulate initial login\fR) option runs the shell specified -in the \fIpasswd\fR\|(@mansectform@) entry of the user that the command is -being run as. The command name argument given to the shell begins -with a `\f(CW\*(C`\-\*(C'\fR' to tell the shell to run as a login shell. \fBsudo\fR -attempts to change to that user's home directory before running the -shell. It also initializes the environment, leaving \fI\s-1TERM\s0\fR -unchanged, setting \fI\s-1HOME\s0\fR, \fI\s-1SHELL\s0\fR, \fI\s-1USER\s0\fR, \fI\s-1LOGNAME\s0\fR, and -\&\fI\s-1PATH\s0\fR, and unsetting all other environment variables. Note that -because the shell to use is determined before the \fIsudoers\fR file -is parsed, a \fIrunas_default\fR setting in \fIsudoers\fR will specify -the user to run the shell as but will not affect which shell is -actually run. -.IP "\-K" 4 +in the \fIpasswd\fR\|(@mansectform@) entry of the target user as a login shell. This +means that login-specific resource files such as \f(CW\*(C`.profile\*(C'\fR or +\&\f(CW\*(C`.login\*(C'\fR will be read by the shell. If a command is specified, +it is passed to the shell for execution. Otherwise, an interactive +shell is executed. \fBsudo\fR attempts to change to that user's home +directory before running the shell. It also initializes the +environment, leaving \fI\s-1DISPLAY\s0\fR and \fI\s-1TERM\s0\fR unchanged, setting +\&\fI\s-1HOME\s0\fR, \fI\s-1SHELL\s0\fR, \fI\s-1USER\s0\fR, \fI\s-1LOGNAME\s0\fR, and \fI\s-1PATH\s0\fR, as well as +the contents of \fI/etc/environment\fR on Linux and \s-1AIX\s0 systems. +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. -.IP "\-k" 4 +.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. -.IP "\-L" 4 +.IP "\-L" 12 .IX Item "-L" The \fB\-L\fR (\fIlist\fR defaults) option will list out the parameters that may be set in a \fIDefaults\fR line along with a short description for each. This option is useful in conjunction with \fIgrep\fR\|(1). -.IP "\-l" 4 -.IX Item "-l" -The \fB\-l\fR (\fIlist\fR) option will list out the allowed (and -forbidden) commands for the invoking user on the current host. -.IP "\-P" 4 +.IP "\-l[l] [\fIcommand\fR]" 12 +.IX Item "-l[l] [command]" +If no \fIcommand\fR is specified, the \fB\-l\fR (\fIlist\fR) option will list +the allowed (and forbidden) commands for the invoking user (or the +user specified by the \fB\-U\fR option) on the current host. If a +\&\fIcommand\fR is specified and is permitted by \fIsudoers\fR, the +fully-qualified path to the command is displayed along with any +command line arguments. If \fIcommand\fR is specified but not allowed, +\&\fBsudo\fR will exit with a status value of 1. If the \fB\-l\fR option is +specified with an \fBl\fR argument (i.e. \fB\-ll\fR), or if \fB\-l\fR +is specified multiple times, a longer list format is used. +.IP "\-n" 12 +.IX Item "-n" +The \fB\-n\fR (\fInon-interactive\fR) option prevents \fBsudo\fR from prompting +the user for a password. If a password is required for the command +to run, \fBsudo\fR will display an error messages and exit. +.IP "\-P" 12 .IX Item "-P" The \fB\-P\fR (\fIpreserve\fR \fIgroup vector\fR) option causes \fBsudo\fR to preserve the invoking user's group vector unaltered. By default, \&\fBsudo\fR will initialize the group vector to the list of groups the target user is in. The real and effective group IDs, however, are still set to match the target user. -.IP "\-p" 4 -.IX Item "-p" +.IP "\-p \fIprompt\fR" 12 +.IX Item "-p prompt" The \fB\-p\fR (\fIprompt\fR) option allows you to override the default password prompt and use a custom one. The following percent (`\f(CW\*(C`%\*(C'\fR') escapes are supported: -.RS 4 +.RS 12 .ie n .IP "%H" 4 .el .IP "\f(CW%H\fR" 4 .IX Item "%H" @@ -364,51 +416,62 @@ expanded to the invoking user's login name .IX Item "%%" two consecutive \f(CW\*(C`%\*(C'\fR characters are collapsed into a single \f(CW\*(C`%\*(C'\fR character .RE -.RS 4 +.RS 12 +.Sp +The prompt specified by the \fB\-p\fR option will override the system +password prompt on systems that support \s-1PAM\s0 unless the +\&\fIpassprompt_override\fR flag is disabled in \fIsudoers\fR. .RE -@SEMAN@.IP "\-r" 4 -@SEMAN@.IX Item "-r" +@SEMAN@.IP "\-r \fIrole\fR" 12 +@SEMAN@.IX Item "-r role" @SEMAN@The \fB\-r\fR (\fIrole\fR) option causes the new (SELinux) security context to @SEMAN@have the role specified by \fIrole\fR. -.IP "\-S" 4 +.IP "\-S" 12 .IX Item "-S" The \fB\-S\fR (\fIstdin\fR) option causes \fBsudo\fR to read the password from the standard input instead of the terminal device. -.IP "\-s" 4 -.IX Item "-s" +.IP "\-s [command]" 12 +.IX Item "-s [command]" The \fB\-s\fR (\fIshell\fR) option runs the shell specified by the \fI\s-1SHELL\s0\fR -environment variable if it is set or the shell as specified -in \fIpasswd\fR\|(@mansectform@). -@SEMAN@.IP "\-t" 4 -@SEMAN@.IX Item "-t" +environment variable if it is set or the shell as specified in +\&\fIpasswd\fR\|(@mansectform@). If a command is specified, it is passed to the shell +for execution. Otherwise, an interactive shell is executed. +@SEMAN@.IP "\-t \fItype\fR" 12 +@SEMAN@.IX Item "-t type" @SEMAN@The \fB\-t\fR (\fItype\fR) option causes the new (SELinux) security context to @SEMAN@have the type specified by \fItype\fR. If no type is specified, the default @SEMAN@type is derived from the specified role. -.IP "\-u" 4 -.IX Item "-u" +.IP "\-U \fIuser\fR" 12 +.IX Item "-U user" +The \fB\-U\fR (\fIother user\fR) option is used in conjunction with the \fB\-l\fR +option to specify the user whose privileges should be listed. Only +root or a user with \fBsudo\fR \f(CW\*(C`ALL\*(C'\fR on the current host may use this +option. +.IP "\-u \fIuser\fR" 12 +.IX Item "-u user" The \fB\-u\fR (\fIuser\fR) option causes \fBsudo\fR to run the specified command as a user other than \fIroot\fR. To specify a \fIuid\fR instead -of a \fIusername\fR, use \fI#uid\fR. When running commands as a \fIuid\fR, +of a \fIuser name\fR, use \fI#uid\fR. When running commands as a \fIuid\fR, many shells require that the '#' be escaped with a backslash ('\e'). Note that if the \fItargetpw\fR Defaults option is set (see \fIsudoers\fR\|(@mansectform@)) it is not possible to run commands with a uid not listed in the password database. -.IP "\-V" 4 +.IP "\-V" 12 .IX Item "-V" The \fB\-V\fR (\fIversion\fR) option causes \fBsudo\fR to print the version number and exit. If the invoking user is already root the \fB\-V\fR option will print out a list of the defaults \fBsudo\fR was compiled with as well as the machine's local network addresses. -.IP "\-v" 4 +.IP "\-v" 12 .IX Item "-v" If given the \fB\-v\fR (\fIvalidate\fR) option, \fBsudo\fR will update the user's timestamp, prompting for the user's password if necessary. This extends the \fBsudo\fR timeout for another \f(CW\*(C`@timeout@\*(C'\fR minutes (or whatever the timeout is set to in \fIsudoers\fR) but does not run a command. -.IP "\-\-" 4 -The \fB\-\-\fR flag indicates that \fBsudo\fR should stop processing command -line arguments. It is most useful in conjunction with the \fB\-s\fR flag. +.IP "\-\-" 12 +The \fB\-\-\fR option indicates that \fBsudo\fR should stop processing command +line arguments. It is most useful in conjunction with the \fB\-s\fR option. .PP Environment variables to be set for the command may also be passed on the command line in the form of \fB\s-1VAR\s0\fR=\fIvalue\fR, e.g. @@ -420,8 +483,8 @@ set or the command matched is \f(CW\*(C`ALL\*(C'\fR, the user may set variables that would overwise be forbidden. See \fIsudoers\fR\|(@mansectform@) for more information. .SH "RETURN VALUES" .IX Header "RETURN VALUES" -Upon successful execution of a program, the return value from \fBsudo\fR -will simply be the return value of the program that was executed. +Upon successful execution of a program, the exit status from \fBsudo\fR +will simply be the exit status of the program that was executed. .PP Otherwise, \fBsudo\fR quits with an exit value of 1 if there is a configuration/permission problem or if \fBsudo\fR cannot execute the @@ -511,7 +574,8 @@ information, please see the \f(CW\*(C`PREVENTING SHELL ESCAPES\*(C'\fR section i .ie n .IP "\*(C`EDITOR\*(C'" 16 .el .IP "\f(CW\*(C`EDITOR\*(C'\fR" 16 .IX Item "EDITOR" -Default editor to use in \fB\-e\fR (sudoedit) mode if \f(CW\*(C`VISUAL\*(C'\fR is not set +Default editor to use in \fB\-e\fR (sudoedit) mode if neither \f(CW\*(C`SUDO_EDITOR\*(C'\fR +nor \f(CW\*(C`VISUAL\*(C'\fR is set .ie n .IP "\*(C`HOME\*(C'" 16 .el .IP "\f(CW\*(C`HOME\*(C'\fR" 16 .IX Item "HOME" @@ -525,30 +589,39 @@ Set to a sane value if the \fIsecure_path\fR sudoers option is set. .el .IP "\f(CW\*(C`SHELL\*(C'\fR" 16 .IX Item "SHELL" Used to determine shell to run with \f(CW\*(C`\-s\*(C'\fR option -.ie n .IP "\*(C`SUDO_PROMPT\*(C'" 16 -.el .IP "\f(CW\*(C`SUDO_PROMPT\*(C'\fR" 16 -.IX Item "SUDO_PROMPT" -Used as the default password prompt +.ie n .IP "\*(C`SUDO_ASKPASS\*(C'" 16 +.el .IP "\f(CW\*(C`SUDO_ASKPASS\*(C'\fR" 16 +.IX Item "SUDO_ASKPASS" +Specifies the path to a helper program used to read the password +if no terminal is available or if the \f(CW\*(C`\-A\*(C'\fR option is specified. .ie n .IP "\*(C`SUDO_COMMAND\*(C'" 16 .el .IP "\f(CW\*(C`SUDO_COMMAND\*(C'\fR" 16 .IX Item "SUDO_COMMAND" Set to the command run by sudo -.ie n .IP "\*(C`SUDO_USER\*(C'" 16 -.el .IP "\f(CW\*(C`SUDO_USER\*(C'\fR" 16 -.IX Item "SUDO_USER" -Set to the login of the user who invoked sudo -.ie n .IP "\*(C`SUDO_UID\*(C'" 16 -.el .IP "\f(CW\*(C`SUDO_UID\*(C'\fR" 16 -.IX Item "SUDO_UID" -Set to the uid of the user who invoked sudo +.ie n .IP "\*(C`SUDO_EDITOR\*(C'" 16 +.el .IP "\f(CW\*(C`SUDO_EDITOR\*(C'\fR" 16 +.IX Item "SUDO_EDITOR" +Default editor to use in \fB\-e\fR (sudoedit) mode .ie n .IP "\*(C`SUDO_GID\*(C'" 16 .el .IP "\f(CW\*(C`SUDO_GID\*(C'\fR" 16 .IX Item "SUDO_GID" -Set to the gid of the user who invoked sudo +Set to the group \s-1ID\s0 of the user who invoked sudo +.ie n .IP "\*(C`SUDO_PROMPT\*(C'" 16 +.el .IP "\f(CW\*(C`SUDO_PROMPT\*(C'\fR" 16 +.IX Item "SUDO_PROMPT" +Used as the default password prompt .ie n .IP "\*(C`SUDO_PS1\*(C'" 16 .el .IP "\f(CW\*(C`SUDO_PS1\*(C'\fR" 16 .IX Item "SUDO_PS1" -If set, \f(CW\*(C`PS1\*(C'\fR will be set to its value +If set, \f(CW\*(C`PS1\*(C'\fR will be set to its value for the program being run +.ie n .IP "\*(C`SUDO_UID\*(C'" 16 +.el .IP "\f(CW\*(C`SUDO_UID\*(C'\fR" 16 +.IX Item "SUDO_UID" +Set to the user \s-1ID\s0 of the user who invoked sudo +.ie n .IP "\*(C`SUDO_USER\*(C'" 16 +.el .IP "\f(CW\*(C`SUDO_USER\*(C'\fR" 16 +.IX Item "SUDO_USER" +Set to the login of the user who invoked sudo .ie n .IP "\*(C`USER\*(C'" 16 .el .IP "\f(CW\*(C`USER\*(C'\fR" 16 .IX Item "USER" @@ -556,15 +629,21 @@ Set to the target user (root unless the \fB\-u\fR option is specified) .ie n .IP "\*(C`VISUAL\*(C'" 16 .el .IP "\f(CW\*(C`VISUAL\*(C'\fR" 16 .IX Item "VISUAL" -Default editor to use in \fB\-e\fR (sudoedit) mode +Default editor to use in \fB\-e\fR (sudoedit) mode if \f(CW\*(C`SUDO_EDITOR\*(C'\fR +is not set .SH "FILES" .IX Header "FILES" -.IP "\fI@sysconfdir@/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 -.IP "\fI@timedir@\fR" 24 +.ie n .IP "\fI@timedir@\fR" 24 +.el .IP "\fI@timedir@\fR" 24 .IX Item "@timedir@" Directory containing timestamps +.IP "\fI/etc/environment\fR" 24 +.IX Item "/etc/environment" +Initial environment for \fB\-i\fR mode on Linux and \s-1AIX\s0 .SH "EXAMPLES" .IX Header "EXAMPLES" Note: the following examples assume suitable \fIsudoers\fR\|(@mansectform@) entries. @@ -579,19 +658,19 @@ To list the home directory of user yazza on a machine where the file system holding ~yazza is not exported as root: .PP .Vb 1 -\& $ sudo -u yazza ls ~yazza +\& $ sudo \-u yazza ls ~yazza .Ve .PP To edit the \fIindex.html\fR file as user www: .PP .Vb 1 -\& $ sudo -u www vi ~www/htdocs/index.html +\& $ sudo \-u www vi ~www/htdocs/index.html .Ve .PP To shutdown a machine: .PP .Vb 1 -\& $ sudo shutdown -r +15 "quick reboot" +\& $ sudo shutdown \-r +15 "quick reboot" .Ve .PP To make a usage listing of the directories in the /home @@ -599,7 +678,7 @@ partition. Note that this runs the commands in a sub-shell to make the \f(CW\*(C`cd\*(C'\fR and file redirection work. .PP .Vb 1 -\& $ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE" +\& $ sudo sh \-c "cd /home ; du \-s * | sort \-rn > USAGE" .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" @@ -611,9 +690,8 @@ to make the \f(CW\*(C`cd\*(C'\fR and file redirection work. Many people have worked on \fBsudo\fR over the years; this version consists of code written primarily by: .PP -.Vb 2 +.Vb 1 \& Todd C. Miller -\& Chris Jepeway .Ve .PP See the \s-1HISTORY\s0 file in the \fBsudo\fR distribution or visit diff --git a/sudo.pod b/sudo.pod index 33fe5d2..e96f044 100644 --- a/sudo.pod +++ b/sudo.pod @@ -1,4 +1,4 @@ -Copyright (c) 1994-1996, 1998-2005, 2007 +Copyright (c) 1994-1996, 1998-2005, 2007-2008 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.70.2.24 2008/02/19 18:22:11 millert Exp $ +$Sudo: sudo.pod,v 1.120 2008/11/15 18:34:01 millert Exp $ =pod =head1 NAME @@ -27,21 +27,26 @@ sudo, sudoedit - execute a command as another user =head1 SYNOPSIS -B B<-h> | B<-K> | B<-k> | B<-L> | B<-l> | B<-V> | B<-v> +B [B<-n>] B<-h> | B<-K> | B<-k> | B<-L> | B<-V> | B<-v> -B [B<-bEHPS>] +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<-AbEHnPS>] S<[B<-a> I]> +S<[B<-C> I]> S<[B<-c> I|I<->]> -S<[B<-p> I]> +S<[B<-g> I|I<#gid>]> S<[B<-p> I]> S<[B<-r> I]> S<[B<-t> I]> S<[B<-u> I|I<#uid>]> -S<[B=I]> S<{B<-i> | B<-s> | I}> +S<[B=I]> S<[B<-i> | B<-s>]> [I] -B [B<-S>] +B [B<-AnS>] S<[B<-a> I]> +S<[B<-C> I]> S<[B<-c> I|I<->]> -S<[B<-p> I]> S<[B<-u> I|I<#uid>]> -file ... +S<[B<-g> I|I<#gid>]> S<[B<-p> I]> +S<[B<-u> I|I<#uid>]> file ... =head1 DESCRIPTION @@ -63,17 +68,17 @@ When invoked as B, the B<-e> option (described below), is implied. B determines who is an authorized user by consulting the file -F<@sysconfdir@/sudoers>. By giving B the B<-v> flag, a user -can update the time stamp without running a I. The password -prompt itself will also time out if the user's password is not -entered within C<@password_timeout@> minutes (unless overridden via -I). +F<@sysconfdir@/sudoers>. By running B with the B<-v> option, +a user can update the time stamp without running a I. The +password prompt itself will also time out if the user's password +is not entered within C<@password_timeout@> minutes (unless overridden +via I). If a user who is not listed in the I file tries to run a command via B, mail is sent to the proper authorities, as defined at configure time or in the I file (defaults to C<@mailto@>). Note that the mail will not be sent if an unauthorized -user tries to run sudo with the B<-l> or B<-v> flags. This allows +user tries to run sudo with the B<-l> or B<-v> option. This allows users to determine for themselves whether or not they are allowed to use B. @@ -81,7 +86,7 @@ If B is run by root and the C environment variable is set, B will use this value to determine who the actual user is. This can be used by a user to log commands through sudo even when a root shell has been invoked. It also allows the B<-e> -flag to remain useful even when being run via a sudo-run script or +option to remain useful even when being run via a sudo-run script or program. Note however, that the sudoers lookup is still done for root, not the user specified by C. @@ -94,9 +99,19 @@ or via the I file. B accepts the following command line options: -=over 4 +=over 12 + +=item -A -=item -a +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. + +=item -a I The B<-a> (I) option causes B to use the specified authentication type when validating the user, as allowed @@ -111,11 +126,21 @@ The B<-b> (I) option tells B to run the given command in the background. Note that if you use the B<-b> option you cannot use shell job control to manipulate the process. -=item -c +=item -C I + +Normally, B will close all open file descriptors other than +standard input, standard output and standard error. The B<-C> +(I) option allows the user to specify a starting point +above the standard error (file descriptor three). Values less than +three are not permitted. This option is only available if the +administrator has enabled the I option in +L. + +=item -c I The B<-c> (I) option causes B to run the specified command with resources limited by the specified login class. The I -argument can be either a class name as defined in C, +argument can be either a class name as defined in F, or a single '-' character. Specifying a I of C<-> indicates that the command should be run restricted by the default login capabilities for the user the command is run as. If the I @@ -147,10 +172,10 @@ set to the invoking user. =item 2. -The editor specified by the C or C environment -variables is run to edit the temporary files. If neither C -nor C are set, the program listed in the I I -variable is used. +The editor specified by the C, C or C +environment variables is run to edit the temporary files. If none +of C, C or C are set, the first program +listed in the I I variable is used. =item 3. @@ -166,6 +191,18 @@ B is unable to update a file with its edited version, the user will receive a warning and the edited copy will remain in a temporary file. +=item -g I + +Normally, B sets the primary group to the one specified by +the passwd database for the user the command is being run as (by +default, root). The B<-g> (I) option causes B to run +the specified command with the primary group set to I. To +specify a I instead of a I, use I<#gid>. When +running commands as a I, many shells require that the '#' be +escaped with a backslash ('\'). If no B<-u> option is specified, +the command will be run as the invoking user (not root). In either +case, the primary group will be set to I. + =item -H The B<-H> (I) option sets the C environment variable @@ -177,20 +214,19 @@ in passwd(5). By default, B does not modify C The B<-h> (I) option causes B to print a usage message and exit. -=item -i +=item -i [command] The B<-i> (I) option runs the shell specified -in the L entry of the user that the command is -being run as. The command name argument given to the shell begins -with a `C<->' to tell the shell to run as a login shell. B -attempts to change to that user's home directory before running the -shell. It also initializes the environment, leaving I -unchanged, setting I, I, I, I, and -I, and unsetting all other environment variables. Note that -because the shell to use is determined before the I file -is parsed, a I setting in I will specify -the user to run the shell as but will not affect which shell is -actually run. +in the L entry of the target user as a login shell. This +means that login-specific resource files such as C<.profile> or +C<.login> will be read by the shell. If a command is specified, +it is passed to the shell for execution. Otherwise, an interactive +shell is executed. B attempts to change to that user's home +directory before running the shell. It also initializes the +environment, leaving I and I unchanged, setting +I, I, I, I, and I, as well as +the contents of F on Linux and AIX systems. +All other environment variables are removed. =item -K @@ -212,10 +248,23 @@ The B<-L> (I defaults) option will list out the parameters that may be set in a I line along with a short description for each. This option is useful in conjunction with L. -=item -l +=item -l[l] [I] -The B<-l> (I) option will list out the allowed (and -forbidden) commands for the invoking user on the current host. +If no I is specified, the B<-l> (I) option will list +the allowed (and forbidden) commands for the invoking user (or the +user specified by the B<-U> option) on the current host. If a +I is specified and is permitted by I, the +fully-qualified path to the command is displayed along with any +command line arguments. If I is specified but not allowed, +B will exit with a status value of 1. If the B<-l> option is +specified with an B argument (i.e. B<-ll>), or if B<-l> +is specified multiple times, a longer list format is used. + +=item -n + +The B<-n> (I) option prevents B from prompting +the user for a password. If a password is required for the command +to run, B will display an error messages and exit. =item -P @@ -225,7 +274,7 @@ B will initialize the group vector to the list of groups the target user is in. The real and effective group IDs, however, are still set to match the target user. -=item -p +=item -p I The B<-p> (I) option allows you to override the default password prompt and use a custom one. The following percent (`C<%>') @@ -263,7 +312,11 @@ two consecutive C<%> characters are collapsed into a single C<%> character =back -=item -r +The prompt specified by the B<-p> option will override the system +password prompt on systems that support PAM unless the +I flag is disabled in I. + +=item -r I The B<-r> (I) option causes the new (SELinux) security context to have the role specified by I. @@ -273,23 +326,31 @@ have the role specified by I. The B<-S> (I) option causes B to read the password from the standard input instead of the terminal device. -=item -s +=item -s [command] The B<-s> (I) option runs the shell specified by the I -environment variable if it is set or the shell as specified -in L. +environment variable if it is set or the shell as specified in +L. If a command is specified, it is passed to the shell +for execution. Otherwise, an interactive shell is executed. -=item -t +=item -t I The B<-t> (I) option causes the new (SELinux) security context to have the type specified by I. If no type is specified, the default type is derived from the specified role. -=item -u +=item -U I + +The B<-U> (I) option is used in conjunction with the B<-l> +option to specify the user whose privileges should be listed. Only +root or a user with B C on the current host may use this +option. + +=item -u I The B<-u> (I) option causes B to run the specified command as a user other than I. To specify a I instead -of a I, use I<#uid>. When running commands as a I, +of a I, use I<#uid>. When running commands as a I, many shells require that the '#' be escaped with a backslash ('\'). Note that if the I Defaults option is set (see L) it is not possible to run commands with a uid not listed in the @@ -312,8 +373,8 @@ a command. =item -- -The B<--> flag indicates that B should stop processing command -line arguments. It is most useful in conjunction with the B<-s> flag. +The B<--> option indicates that B should stop processing command +line arguments. It is most useful in conjunction with the B<-s> option. =back @@ -328,8 +389,8 @@ that would overwise be forbidden. See L for more information. =head1 RETURN VALUES -Upon successful execution of a program, the return value from B -will simply be the return value of the program that was executed. +Upon successful execution of a program, the exit status from B +will simply be the exit status of the program that was executed. Otherwise, B quits with an exit value of 1 if there is a configuration/permission problem or if B cannot execute the @@ -423,7 +484,8 @@ B utilizes the following environment variables: =item C -Default editor to use in B<-e> (sudoedit) mode if C is not set +Default editor to use in B<-e> (sudoedit) mode if neither C +nor C is set =item C @@ -438,29 +500,38 @@ Set to a sane value if the I sudoers option is set. Used to determine shell to run with C<-s> option -=item C +=item C -Used as the default password prompt +Specifies the path to a helper program used to read the password +if no terminal is available or if the C<-A> option is specified. =item C Set to the command run by sudo -=item C +=item C -Set to the login of the user who invoked sudo +Default editor to use in B<-e> (sudoedit) mode -=item C +=item C -Set to the uid of the user who invoked sudo +Set to the group ID of the user who invoked sudo -=item C +=item C -Set to the gid of the user who invoked sudo +Used as the default password prompt =item C -If set, C will be set to its value +If set, C will be set to its value for the program being run + +=item C + +Set to the user ID of the user who invoked sudo + +=item C + +Set to the login of the user who invoked sudo =item C @@ -468,7 +539,8 @@ Set to the target user (root unless the B<-u> option is specified) =item C -Default editor to use in B<-e> (sudoedit) mode +Default editor to use in B<-e> (sudoedit) mode if C +is not set =back @@ -484,6 +556,10 @@ List of who can run what Directory containing timestamps +=item F + +Initial environment for B<-i> mode on Linux and AIX + =back =head1 EXAMPLES @@ -525,7 +601,6 @@ Many people have worked on B over the years; this version consists of code written primarily by: Todd C. Miller - Chris Jepeway See the HISTORY file in the B distribution or visit http://www.sudo.ws/sudo/history.html for a short history diff --git a/sudo.psf b/sudo.psf new file mode 100644 index 0000000..59ddef2 --- /dev/null +++ b/sudo.psf @@ -0,0 +1,91 @@ +# PSF file for sudo +# +# See http://www.software.hp.com/products/SD_AT_HP/docs/cookbook.html +# for details. +# +# To create sudo.depot, run: +# +# swpackage -x target_type=tape -d sudo.depot -s sudo.psf +# +# To install, run: +# +# swinstall -s sudo.depot sudo +# +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# +vendor + tag GratiSoft + title "GratiSoft, Inc." + description "GratiSoft, Inc., http://www.gratisoft.us/" +end +# +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# +product + tag sudo + title "Sudo" + description "execute a command as another user" + revision @VERSION@ + # + architecture S700/S800_HPUX_10/11 + machine_type 9000/[78]* + os_name HP-UX + os_release ?.10.*|?.11.* + os_version * + # + fileset + tag bin + title "sudo binaries" + revision @VERSION@ + + file -m 4111 -o root -g root sudo /usr/local/bin/sudo + file -m 111 -o root -g bin visudo /usr/local/sbin/visudo + + postinstall sudo-exec.postinstall + end + # + fileset + tag libexec + title "sudo noexec library" + revision @VERSION@ + + file -m 555 -o root -g bin sudo_noexec.sl /usr/local/libexec/sudo_noexec.sl + end + # + fileset + tag manpages + title "sudo manpages" + revision @VERSION@ + + file -m 444 -g bin -o root sudo.man /usr/local/man/man1m/sudo.1m + file -m 444 -g bin -o root sudoers.man /usr/local/man/man4/sudoers.4 + file -m 444 -g bin -o root visudo.man /usr/local/man/man1m/visudo.1m + + postinstall sudo-man.postinstall + end + # + fileset + tag doc + title "sudo doc" + revision @VERSION@ + + file -m 444 -g bin -o root BUGS /usr/local/doc/sudo/BUGS + file -m 444 -g bin -o root CHANGES /usr/local/doc/sudo/CHANGES + file -m 444 -g bin -o root HISTORY /usr/local/doc/sudo/HISTORY + file -m 444 -g bin -o root LICENSE /usr/local/doc/sudo/LICENSE + file -m 444 -g bin -o root README /usr/local/doc/sudo/README + file -m 444 -g bin -o root TROUBLESHOOTING /usr/local/doc/sudo/TROUBLESHOOTING + file -m 444 -g bin -o root UPGRADE /usr/local/doc/sudo/UPGRADE + file -m 444 -g bin -o root sample.syslog.conf /usr/local/doc/sudo/sample.syslog.conf + file -m 444 -g bin -o root sample.sudoers /usr/local/doc/sudo/sample.sudoers + end + # + fileset + tag config + title "sudo config files" + revision @VERSION@ + file -m 444 -g bin -o root sudoers /usr/local/doc/sudo/sudoers + + postinstall sudo-config.postinstall + end +end diff --git a/sudo.tab.c b/sudo.tab.c deleted file mode 100644 index 0e40bef..0000000 --- a/sudo.tab.c +++ /dev/null @@ -1,2270 +0,0 @@ -#ifndef lint -/*static char yysccsid[] = "from: @(#)yaccpar 1.9 (Berkeley) 02/21/93";*/ -static char yyrcsid[] -#if __GNUC__ >= 2 - __attribute__ ((unused)) -#endif /* __GNUC__ >= 2 */ - = "$OpenBSD: skeleton.c,v 1.28 2007/09/03 21:14:58 deraadt Exp $"; -#endif -#include -#define YYBYACC 1 -#define YYMAJOR 1 -#define YYMINOR 9 -#define YYLEX yylex() -#define YYEMPTY -1 -#define yyclearin (yychar=(YYEMPTY)) -#define yyerrok (yyerrflag=0) -#define YYRECOVERING() (yyerrflag!=0) -#define YYPREFIX "yy" -#line 2 "parse.yacc" -/* - * Copyright (c) 1996, 1998-2004, 2007 - * 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. - * - * 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. - */ - -/* - * XXX - the whole opFOO naming thing is somewhat bogus. - * - * XXX - the way things are stored for printmatches is stupid, - * they should be stored as elements in an array and then - * list_matches() can format things the way it wants. - */ - -#include - -#include -#include -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif /* STDC_HEADERS */ -#ifdef HAVE_STRING_H -# include -#else -# ifdef HAVE_STRINGS_H -# include -# endif -#endif /* HAVE_STRING_H */ -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ -#include -#if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__) -# include -#endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */ -#ifdef HAVE_LSEARCH -# include -#endif /* HAVE_LSEARCH */ -#include - -#include "sudo.h" -#include "parse.h" - -#ifndef HAVE_LSEARCH -#include "emul/search.h" -#endif /* HAVE_LSEARCH */ - -#ifndef lint -__unused static const char rcsid[] = "$Sudo: sudo.tab.c,v 1.76.2.14 2008/02/27 20:34:42 millert Exp $"; -#endif /* lint */ - -/* - * We must define SIZE_MAX for yacc's skeleton.c. - * If there is no SIZE_MAX or SIZE_T_MAX we have to assume that size_t - * could be signed (as it is on SunOS 4.x). - */ -#ifndef SIZE_MAX -# ifdef SIZE_T_MAX -# define SIZE_MAX SIZE_T_MAX -# else -# define SIZE_MAX INT_MAX -# endif /* SIZE_T_MAX */ -#endif /* SIZE_MAX */ - -/* - * Globals - */ -extern int sudolineno, parse_error; -int errorlineno = -1; -int clearaliases = TRUE; -int printmatches = FALSE; -int pedantic = FALSE; -int keepall = FALSE; -int quiet = FALSE; -int used_runas = FALSE; - -/* - * Alias types - */ -#define HOST_ALIAS 1 -#define CMND_ALIAS 2 -#define USER_ALIAS 3 -#define RUNAS_ALIAS 4 - -#define SETMATCH(_var, _val) do { \ - if ((_var) == UNSPEC || (_val) != NOMATCH) \ - (_var) = (_val); \ -} while (0) - -#define SETNMATCH(_var, _val) do { \ - if ((_val) != NOMATCH) \ - (_var) = ! (_val); \ - else if ((_var) == UNSPEC) \ - (_var) = NOMATCH; \ -} while (0) - -#define SETENV_RESET \ - if (setenv_ok == IMPLIED) setenv_ok = def_setenv ? TRUE : UNSPEC - -/* - * The matching stack, initial space allocated in init_parser(). - */ -struct matchstack *match; -int top = 0, stacksize = 0; - -#define push \ - do { \ - if (top >= stacksize) { \ - while ((stacksize += STACKINCREMENT) < top); \ - match = (struct matchstack *) erealloc3(match, stacksize, sizeof(struct matchstack)); \ - } \ - match[top].user = UNSPEC; \ - match[top].cmnd = UNSPEC; \ - match[top].host = UNSPEC; \ - match[top].runas = UNSPEC; \ - match[top].nopass = def_authenticate ? UNSPEC : TRUE; \ - match[top].noexec = def_noexec ? TRUE : UNSPEC; \ - match[top].setenv = def_setenv ? TRUE : UNSPEC; \ - match[top].role = NULL; \ - match[top].type = NULL; \ - top++; \ - } while (0) - -#define pushcp \ - do { \ - if (top >= stacksize) { \ - while ((stacksize += STACKINCREMENT) < top); \ - match = (struct matchstack *) erealloc3(match, stacksize, sizeof(struct matchstack)); \ - } \ - match[top].user = match[top-1].user; \ - match[top].cmnd = match[top-1].cmnd; \ - match[top].host = match[top-1].host; \ - match[top].runas = match[top-1].runas; \ - match[top].nopass = match[top-1].nopass; \ - match[top].noexec = match[top-1].noexec; \ - match[top].setenv = match[top-1].setenv; \ - match[top].role = estrdup(match[top-1].role); \ - match[top].type = estrdup(match[top-1].type); \ - top++; \ - } while (0) - -#define pop \ - do { \ - if (top == 0) \ - yyerror("matching stack underflow"); \ - else { \ - efree(match[top-1].role); \ - efree(match[top-1].type); \ - top--; \ - } \ - } while (0) - - -/* - * For testing if foo_matches variable was set to TRUE or FALSE - */ -#define MATCHED(_v) ((_v) >= 0) - -/* - * Shortcuts for append() - */ -#define append_cmnd(s, p) append(s, &cm_list[cm_list_len].cmnd, \ - &cm_list[cm_list_len].cmnd_len, &cm_list[cm_list_len].cmnd_size, p) - -#define append_runas(s, p) append(s, &cm_list[cm_list_len].runas, \ - &cm_list[cm_list_len].runas_len, &cm_list[cm_list_len].runas_size, p) - -#define append_role(s, p) append(s, &cm_list[cm_list_len].role, \ - &cm_list[cm_list_len].role_len, &cm_list[cm_list_len].role_size, p) - -#define append_type(s, p) append(s, &cm_list[cm_list_len].type, \ - &cm_list[cm_list_len].type_len, &cm_list[cm_list_len].type_size, p) - -#define append_entries(s, p) append(s, &ga_list[ga_list_len-1].entries, \ - &ga_list[ga_list_len-1].entries_len, \ - &ga_list[ga_list_len-1].entries_size, p) - -/* - * The stack for printmatches. A list of allowed commands for the user. - */ -static struct command_match *cm_list = NULL; -static size_t cm_list_len = 0, cm_list_size = 0; - -/* - * List of Cmnd_Aliases and expansions for `sudo -l' - */ -static int in_alias = FALSE; -static size_t ga_list_len = 0, ga_list_size = 0; -static struct generic_alias *ga_list = NULL; - -/* - * Does this Defaults list pertain to this user? - */ -static int defaults_matches = FALSE; - -/* - * Local protoypes - */ -static int add_alias __P((char *, int, int)); -static void append __P((char *, char **, size_t *, size_t *, char *)); -static void expand_ga_list __P((void)); -static void expand_match_list __P((void)); -static aliasinfo *find_alias __P((char *, int)); -static void more_aliases __P((void)); - void init_parser __P((void)); - void yyerror __P((char *)); - -void -yyerror(s) - char *s; -{ - /* Save the line the first error occurred on. */ - if (errorlineno == -1) - errorlineno = sudolineno ? sudolineno - 1 : 0; - if (s && !quiet) { -#ifndef TRACELEXER - (void) fprintf(stderr, ">>> sudoers file: %s, line %d <<<\n", s, - sudolineno ? sudolineno - 1 : 0); -#else - (void) fprintf(stderr, "<*> "); -#endif - } - parse_error = TRUE; -} -#line 251 "parse.yacc" -#ifndef YYSTYPE_DEFINED -#define YYSTYPE_DEFINED -typedef union { - char *string; - int BOOLEAN; - struct sudo_command command; - int tok; - struct selinux_info seinfo; -} YYSTYPE; -#endif /* YYSTYPE_DEFINED */ -#line 279 "sudo.tab.c" -#define COMMAND 257 -#define ALIAS 258 -#define DEFVAR 259 -#define NTWKADDR 260 -#define NETGROUP 261 -#define USERGROUP 262 -#define WORD 263 -#define DEFAULTS 264 -#define DEFAULTS_HOST 265 -#define DEFAULTS_USER 266 -#define DEFAULTS_RUNAS 267 -#define RUNAS 268 -#define NOPASSWD 269 -#define PASSWD 270 -#define NOEXEC 271 -#define EXEC 272 -#define SETENV 273 -#define NOSETENV 274 -#define ALL 275 -#define COMMENT 276 -#define HOSTALIAS 277 -#define CMNDALIAS 278 -#define USERALIAS 279 -#define RUNASALIAS 280 -#define ERROR 281 -#define TYPE 282 -#define ROLE 283 -#define YYERRCODE 256 -#if defined(__cplusplus) || defined(__STDC__) -const short yylhs[] = -#else -short yylhs[] = -#endif - { -1, - 0, 0, 10, 10, 12, 10, 10, 10, 10, 10, - 10, 18, 19, 21, 19, 22, 19, 24, 19, 20, - 20, 25, 25, 25, 25, 25, 13, 13, 26, 28, - 28, 2, 2, 2, 2, 2, 27, 27, 31, 29, - 33, 34, 33, 8, 9, 7, 7, 7, 7, 7, - 30, 30, 5, 5, 4, 35, 4, 3, 3, 3, - 3, 3, 32, 32, 32, 32, 32, 32, 32, 1, - 1, 1, 15, 15, 37, 36, 23, 23, 16, 16, - 39, 38, 40, 40, 17, 17, 42, 41, 14, 14, - 44, 43, 11, 11, 45, 45, 6, 6, 6, 6, - 6, -}; -#if defined(__cplusplus) || defined(__STDC__) -const short yylen[] = -#else -short yylen[] = -#endif - { 2, - 1, 2, 1, 2, 0, 3, 2, 2, 2, 2, - 1, 2, 1, 0, 3, 0, 3, 0, 3, 1, - 3, 1, 2, 3, 3, 3, 1, 3, 3, 1, - 2, 1, 1, 1, 1, 1, 1, 3, 0, 5, - 1, 0, 3, 3, 3, 0, 1, 1, 2, 2, - 0, 2, 1, 3, 1, 0, 3, 1, 1, 1, - 1, 1, 0, 2, 2, 2, 2, 2, 2, 1, - 1, 1, 1, 3, 0, 4, 1, 3, 1, 3, - 0, 4, 1, 3, 1, 3, 0, 4, 1, 3, - 0, 4, 1, 3, 1, 2, 1, 1, 1, 1, - 1, -}; -#if defined(__cplusplus) || defined(__STDC__) -const short yydefred[] = -#else -short yydefred[] = -#endif - { 0, - 0, 13, 18, 14, 16, 3, 0, 0, 0, 0, - 0, 1, 0, 11, 0, 4, 0, 0, 0, 75, - 0, 73, 81, 0, 79, 91, 0, 89, 87, 0, - 85, 2, 100, 99, 98, 97, 101, 0, 95, 0, - 93, 0, 0, 12, 0, 36, 33, 34, 35, 32, - 0, 30, 0, 77, 0, 61, 60, 59, 58, 62, - 56, 55, 53, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 96, 0, 0, 0, 27, 0, 0, 0, - 23, 0, 31, 0, 0, 0, 0, 74, 0, 80, - 0, 90, 0, 86, 94, 0, 39, 24, 25, 26, - 21, 78, 57, 54, 0, 72, 71, 70, 42, 41, - 83, 0, 0, 0, 28, 0, 37, 0, 0, 0, - 39, 0, 0, 43, 84, 38, 0, 0, 0, 63, - 0, 0, 0, 0, 0, 49, 50, 45, 44, 64, - 65, 66, 67, 68, 69, 40, -}; -#if defined(__cplusplus) || defined(__STDC__) -const short yydgoto[] = -#else -short yydgoto[] = -#endif - { 11, - 110, 52, 62, 63, 64, 39, 130, 131, 132, 12, - 40, 13, 75, 27, 21, 24, 30, 14, 15, 44, - 18, 19, 76, 17, 45, 77, 116, 54, 117, 123, - 118, 135, 111, 119, 85, 22, 65, 25, 67, 112, - 31, 71, 28, 69, 41, -}; -#if defined(__cplusplus) || defined(__STDC__) -const short yysindex[] = -#else -short yysindex[] = -#endif - { -247, - -248, 0, 0, 0, 0, 0, -211, -210, -205, -201, - -247, 0, 62, 0, -33, 0, 89, 62, 114, 0, - 2, 0, 0, 3, 0, 0, 4, 0, 0, 6, - 0, 0, 0, 0, 0, 0, 0, -251, 0, -28, - 0, -18, -194, 0, 14, 0, 0, 0, 0, 0, - -219, 0, 22, 0, 23, 0, 0, 0, 0, 0, - 0, 0, 0, 24, 8, -211, 9, -210, 10, -205, - 11, -201, 0, 62, 16, -23, 0, -187, -186, -184, - 0, -33, 0, 89, -212, 114, 89, 0, -20, 0, - 62, 0, 114, 0, 0, 89, 0, 0, 0, 0, - 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, - 0, 36, 23, 24, 0, 37, 0, -185, -221, -20, - 0, 114, -268, 0, 0, 0, 24, 21, 25, 0, - -195, -193, -175, -174, 274, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,}; -#if defined(__cplusplus) || defined(__STDC__) -const short yyrindex[] = -#else -short yyrindex[] = -#endif - { 141, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 156, 0, 0, 181, 0, 0, 206, 0, 0, 236, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 261, 0, 0, 0, 0, 0, - 0, 0, -25, 0, -11, 0, 0, 0, 0, 0, - 0, 0, 0, -10, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 300, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, - 0, 52, 78, 104, 0, 130, 0, -29, 0, 0, - 0, 0, 340, 0, 0, 0, 313, 0, 0, 0, - 365, 391, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,}; -#if defined(__cplusplus) || defined(__STDC__) -const short yygindex[] = -#else -short yygindex[] = -#endif - { 0, - -27, 40, 12, 7, -87, 56, 0, -36, -32, 87, - -16, 0, 0, 0, 0, 0, 0, 0, 0, 18, - 0, 0, -14, 0, 0, 5, 0, 19, -19, 0, - 0, 0, -80, 0, 0, 39, 0, 38, 0, 0, - 35, 0, 42, 0, 34, -}; -#define YYTABLESIZE 666 -#if defined(__cplusplus) || defined(__STDC__) -const short yytable[] = -#else -short yytable[] = -#endif - { 43, - 22, 55, 53, 51, 51, 114, 33, 19, 1, 34, - 35, 36, 109, 128, 129, 74, 2, 3, 4, 5, - 84, 15, 17, 37, 79, 76, 80, 16, 6, 7, - 8, 9, 10, 22, 127, 106, 107, 97, 46, 125, - 47, 48, 78, 49, 22, 56, 20, 23, 57, 58, - 59, 82, 26, 108, 146, 50, 29, 82, 76, 66, - 68, 70, 60, 72, 81, 84, 74, 86, 87, 89, - 91, 93, 105, 96, 113, 98, 99, 92, 100, 120, - 121, 133, 122, 76, 82, 134, 128, 138, 139, 129, - 83, 124, 104, 73, 38, 137, 103, 32, 136, 101, - 115, 126, 102, 88, 88, 90, 94, 95, 0, 82, - 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 51, 0, 0, 0, 0, 0, 0, 0, 29, - 0, 0, 0, 0, 0, 92, 88, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, - 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, - 0, 88, 29, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, - 9, 0, 0, 0, 0, 0, 0, 29, 8, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, - 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 42, 0, 51, 51, 46, - 0, 47, 48, 19, 49, 10, 106, 107, 7, 51, - 51, 51, 51, 51, 51, 51, 50, 15, 17, 0, - 0, 0, 51, 51, 108, 0, 22, 0, 22, 0, - 20, 22, 22, 22, 22, 22, 22, 22, 10, 0, - 0, 0, 0, 0, 0, 22, 22, 22, 22, 22, - 22, 76, 0, 76, 0, 0, 76, 76, 76, 76, - 76, 76, 76, 20, 0, 0, 0, 0, 0, 6, - 76, 76, 76, 76, 76, 76, 109, 82, 0, 82, - 0, 0, 82, 82, 82, 82, 82, 82, 82, 33, - 0, 0, 34, 35, 36, 0, 82, 82, 82, 82, - 82, 82, 6, 92, 0, 92, 37, 0, 92, 92, - 92, 92, 92, 92, 92, 52, 46, 0, 47, 48, - 0, 49, 92, 92, 92, 92, 92, 92, 0, 88, - 0, 88, 0, 50, 88, 88, 88, 88, 88, 88, - 88, 56, 46, 0, 57, 58, 59, 0, 88, 88, - 88, 88, 88, 88, 0, 29, 0, 29, 60, 0, - 29, 29, 29, 29, 29, 29, 29, 47, 5, 0, - 0, 5, 5, 5, 29, 29, 29, 29, 29, 29, - 0, 8, 0, 8, 0, 5, 8, 8, 8, 8, - 8, 8, 8, 48, 0, 0, 0, 0, 0, 0, - 8, 8, 8, 8, 8, 8, 9, 0, 9, 0, - 0, 9, 9, 9, 9, 9, 9, 9, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, - 9, 7, 0, 7, 0, 0, 7, 7, 7, 7, - 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, - 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, - 0, 10, 0, 10, 0, 0, 10, 10, 10, 10, - 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, - 10, 10, 10, 10, 10, 10, 20, 0, 20, 0, - 0, 20, 20, 20, 20, 20, 20, 20, 0, 0, - 106, 107, 0, 0, 0, 20, 20, 20, 20, 20, - 20, 0, 140, 141, 142, 143, 144, 145, 108, 0, - 0, 0, 0, 0, 0, 6, 0, 6, 0, 0, - 6, 6, 6, 6, 6, 6, 6, 0, 0, 52, - 52, 0, 0, 0, 6, 6, 6, 6, 6, 6, - 0, 52, 52, 52, 52, 52, 52, 52, 0, 0, - 0, 0, 0, 0, 52, 52, 46, 46, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 46, 46, - 46, 46, 46, 46, 46, 0, 0, 0, 0, 0, - 0, 47, 47, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, - 0, 0, 0, 0, 0, 0, 0, 48, 48, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, - 48, 48, 48, 48, 48, 48, -}; -#if defined(__cplusplus) || defined(__STDC__) -const short yycheck[] = -#else -short yycheck[] = -#endif - { 33, - 0, 18, 17, 33, 33, 93, 258, 33, 256, 261, - 262, 263, 33, 282, 283, 44, 264, 265, 266, 267, - 44, 33, 33, 275, 43, 0, 45, 276, 276, 277, - 278, 279, 280, 33, 122, 257, 258, 61, 258, 120, - 260, 261, 61, 263, 44, 258, 258, 258, 261, 262, - 263, 0, 258, 275, 135, 275, 258, 44, 33, 58, - 58, 58, 275, 58, 259, 44, 44, 44, 61, 61, - 61, 61, 87, 58, 91, 263, 263, 0, 263, 44, - 44, 61, 268, 58, 33, 61, 282, 263, 263, 283, - 51, 119, 86, 38, 33, 132, 85, 11, 131, 82, - 96, 121, 84, 0, 66, 68, 72, 74, -1, 58, - 33, 70, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 33, -1, -1, -1, -1, -1, -1, -1, 0, - -1, -1, -1, -1, -1, 58, 33, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, - -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, - -1, 58, 33, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, - 0, -1, -1, -1, -1, -1, -1, 58, 33, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, - -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 259, -1, 257, 258, 258, - -1, 260, 261, 259, 263, 0, 257, 258, 33, 269, - 270, 271, 272, 273, 274, 275, 275, 259, 259, -1, - -1, -1, 282, 283, 275, -1, 256, -1, 258, -1, - 0, 261, 262, 263, 264, 265, 266, 267, 33, -1, - -1, -1, -1, -1, -1, 275, 276, 277, 278, 279, - 280, 256, -1, 258, -1, -1, 261, 262, 263, 264, - 265, 266, 267, 33, -1, -1, -1, -1, -1, 0, - 275, 276, 277, 278, 279, 280, 33, 256, -1, 258, - -1, -1, 261, 262, 263, 264, 265, 266, 267, 258, - -1, -1, 261, 262, 263, -1, 275, 276, 277, 278, - 279, 280, 33, 256, -1, 258, 275, -1, 261, 262, - 263, 264, 265, 266, 267, 33, 258, -1, 260, 261, - -1, 263, 275, 276, 277, 278, 279, 280, -1, 256, - -1, 258, -1, 275, 261, 262, 263, 264, 265, 266, - 267, 258, 33, -1, 261, 262, 263, -1, 275, 276, - 277, 278, 279, 280, -1, 256, -1, 258, 275, -1, - 261, 262, 263, 264, 265, 266, 267, 33, 258, -1, - -1, 261, 262, 263, 275, 276, 277, 278, 279, 280, - -1, 256, -1, 258, -1, 275, 261, 262, 263, 264, - 265, 266, 267, 33, -1, -1, -1, -1, -1, -1, - 275, 276, 277, 278, 279, 280, 256, -1, 258, -1, - -1, 261, 262, 263, 264, 265, 266, 267, -1, -1, - -1, -1, -1, -1, -1, 275, 276, 277, 278, 279, - 280, 256, -1, 258, -1, -1, 261, 262, 263, 264, - 265, 266, 267, -1, -1, -1, -1, -1, -1, -1, - 275, 276, 277, 278, 279, 280, -1, -1, -1, -1, - -1, 256, -1, 258, -1, -1, 261, 262, 263, 264, - 265, 266, 267, -1, -1, -1, -1, -1, -1, -1, - 275, 276, 277, 278, 279, 280, 256, -1, 258, -1, - -1, 261, 262, 263, 264, 265, 266, 267, -1, -1, - 257, 258, -1, -1, -1, 275, 276, 277, 278, 279, - 280, -1, 269, 270, 271, 272, 273, 274, 275, -1, - -1, -1, -1, -1, -1, 256, -1, 258, -1, -1, - 261, 262, 263, 264, 265, 266, 267, -1, -1, 257, - 258, -1, -1, -1, 275, 276, 277, 278, 279, 280, - -1, 269, 270, 271, 272, 273, 274, 275, -1, -1, - -1, -1, -1, -1, 282, 283, 257, 258, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 269, 270, - 271, 272, 273, 274, 275, -1, -1, -1, -1, -1, - -1, 257, 258, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 269, 270, 271, 272, 273, 274, 275, - -1, -1, -1, -1, -1, -1, -1, 257, 258, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 269, - 270, 271, 272, 273, 274, 275, -}; -#define YYFINAL 11 -#ifndef YYDEBUG -#define YYDEBUG 0 -#endif -#define YYMAXTOKEN 283 -#if YYDEBUG -#if defined(__cplusplus) || defined(__STDC__) -const char * const yyname[] = -#else -char *yyname[] = -#endif - { -"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -"'!'",0,0,0,0,0,0,0,0,0,"'+'","','","'-'",0,0,0,0,0,0,0,0,0,0,0,0,"':'",0,0, -"'='",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -"COMMAND","ALIAS","DEFVAR","NTWKADDR","NETGROUP","USERGROUP","WORD","DEFAULTS", -"DEFAULTS_HOST","DEFAULTS_USER","DEFAULTS_RUNAS","RUNAS","NOPASSWD","PASSWD", -"NOEXEC","EXEC","SETENV","NOSETENV","ALL","COMMENT","HOSTALIAS","CMNDALIAS", -"USERALIAS","RUNASALIAS","ERROR","TYPE","ROLE", -}; -#if defined(__cplusplus) || defined(__STDC__) -const char * const yyrule[] = -#else -char *yyrule[] = -#endif - {"$accept : file", -"file : entry", -"file : file entry", -"entry : COMMENT", -"entry : error COMMENT", -"$$1 :", -"entry : $$1 userlist privileges", -"entry : USERALIAS useraliases", -"entry : HOSTALIAS hostaliases", -"entry : CMNDALIAS cmndaliases", -"entry : RUNASALIAS runasaliases", -"entry : defaults_line", -"defaults_line : defaults_type defaults_list", -"defaults_type : DEFAULTS", -"$$2 :", -"defaults_type : DEFAULTS_USER $$2 userlist", -"$$3 :", -"defaults_type : DEFAULTS_RUNAS $$3 runaslist", -"$$4 :", -"defaults_type : DEFAULTS_HOST $$4 hostlist", -"defaults_list : defaults_entry", -"defaults_list : defaults_entry ',' defaults_list", -"defaults_entry : DEFVAR", -"defaults_entry : '!' DEFVAR", -"defaults_entry : DEFVAR '=' WORD", -"defaults_entry : DEFVAR '+' WORD", -"defaults_entry : DEFVAR '-' WORD", -"privileges : privilege", -"privileges : privileges ':' privilege", -"privilege : hostlist '=' cmndspeclist", -"ophost : host", -"ophost : '!' host", -"host : ALL", -"host : NTWKADDR", -"host : NETGROUP", -"host : WORD", -"host : ALIAS", -"cmndspeclist : cmndspec", -"cmndspeclist : cmndspeclist ',' cmndspec", -"$$5 :", -"cmndspec : $$5 runasspec selinux cmndtag opcmnd", -"opcmnd : cmnd", -"$$6 :", -"opcmnd : '!' $$6 cmnd", -"rolespec : ROLE '=' WORD", -"typespec : TYPE '=' WORD", -"selinux :", -"selinux : rolespec", -"selinux : typespec", -"selinux : rolespec typespec", -"selinux : typespec rolespec", -"runasspec :", -"runasspec : RUNAS runaslist", -"runaslist : oprunasuser", -"runaslist : runaslist ',' oprunasuser", -"oprunasuser : runasuser", -"$$7 :", -"oprunasuser : '!' $$7 runasuser", -"runasuser : WORD", -"runasuser : USERGROUP", -"runasuser : NETGROUP", -"runasuser : ALIAS", -"runasuser : ALL", -"cmndtag :", -"cmndtag : cmndtag NOPASSWD", -"cmndtag : cmndtag PASSWD", -"cmndtag : cmndtag NOEXEC", -"cmndtag : cmndtag EXEC", -"cmndtag : cmndtag SETENV", -"cmndtag : cmndtag NOSETENV", -"cmnd : ALL", -"cmnd : ALIAS", -"cmnd : COMMAND", -"hostaliases : hostalias", -"hostaliases : hostaliases ':' hostalias", -"$$8 :", -"hostalias : ALIAS $$8 '=' hostlist", -"hostlist : ophost", -"hostlist : hostlist ',' ophost", -"cmndaliases : cmndalias", -"cmndaliases : cmndaliases ':' cmndalias", -"$$9 :", -"cmndalias : ALIAS $$9 '=' cmndlist", -"cmndlist : opcmnd", -"cmndlist : cmndlist ',' opcmnd", -"runasaliases : runasalias", -"runasaliases : runasaliases ':' runasalias", -"$$10 :", -"runasalias : ALIAS $$10 '=' runaslist", -"useraliases : useralias", -"useraliases : useraliases ':' useralias", -"$$11 :", -"useralias : ALIAS $$11 '=' userlist", -"userlist : opuser", -"userlist : userlist ',' opuser", -"opuser : user", -"opuser : '!' user", -"user : WORD", -"user : USERGROUP", -"user : NETGROUP", -"user : ALIAS", -"user : ALL", -}; -#endif -#ifdef YYSTACKSIZE -#undef YYMAXDEPTH -#define YYMAXDEPTH YYSTACKSIZE -#else -#ifdef YYMAXDEPTH -#define YYSTACKSIZE YYMAXDEPTH -#else -#define YYSTACKSIZE 10000 -#define YYMAXDEPTH 10000 -#endif -#endif -#define YYINITSTACKSIZE 200 -/* LINTUSED */ -int yydebug; -int yynerrs; -int yyerrflag; -int yychar; -short *yyssp; -YYSTYPE *yyvsp; -YYSTYPE yyval; -YYSTYPE yylval; -short *yyss; -short *yysslim; -YYSTYPE *yyvs; -int yystacksize; -#line 1053 "parse.yacc" - -#define MOREALIASES (32) -aliasinfo *aliases = NULL; -size_t naliases = 0; -size_t nslots = 0; - - -/* - * Compare two aliasinfo structures, strcmp() style. - * Note that we do *not* compare their values. - */ -static int -aliascmp(a1, a2) - const VOID *a1, *a2; -{ - int r; - aliasinfo *ai1, *ai2; - - ai1 = (aliasinfo *) a1; - ai2 = (aliasinfo *) a2; - if ((r = strcmp(ai1->name, ai2->name)) == 0) - r = ai1->type - ai2->type; - - return(r); -} - -/* - * Compare two generic_alias structures, strcmp() style. - */ -static int -genaliascmp(entry, key) - const VOID *entry, *key; -{ - int r; - struct generic_alias *ga1, *ga2; - - ga1 = (struct generic_alias *) key; - ga2 = (struct generic_alias *) entry; - if ((r = strcmp(ga1->alias, ga2->alias)) == 0) - r = ga1->type - ga2->type; - - return(r); -} - - -/* - * Adds the named alias of the specified type to the aliases list. - */ -static int -add_alias(alias, type, val) - char *alias; - int type; - int val; -{ - aliasinfo ai, *aip; - size_t onaliases; - char s[512]; - - if (naliases >= nslots) - more_aliases(); - - ai.type = type; - ai.val = val; - ai.name = estrdup(alias); - onaliases = naliases; - - aip = (aliasinfo *) lsearch((VOID *)&ai, (VOID *)aliases, &naliases, - sizeof(ai), aliascmp); - if (aip == NULL) { - (void) snprintf(s, sizeof(s), "Aliases corrupted defining alias `%s'", - alias); - yyerror(s); - return(FALSE); - } - if (onaliases == naliases) { - (void) snprintf(s, sizeof(s), "Alias `%s' already defined", alias); - yyerror(s); - return(FALSE); - } - - return(TRUE); -} - -/* - * Searches for the named alias of the specified type. - */ -static aliasinfo * -find_alias(alias, type) - char *alias; - int type; -{ - aliasinfo ai; - - ai.name = alias; - ai.type = type; - - return((aliasinfo *) lfind((VOID *)&ai, (VOID *)aliases, &naliases, - sizeof(ai), aliascmp)); -} - -/* - * Allocates more space for the aliases list. - */ -static void -more_aliases() -{ - - nslots += MOREALIASES; - aliases = (aliasinfo *) erealloc3(aliases, nslots, sizeof(aliasinfo)); -} - -/* - * Lists the contents of the aliases list. - */ -void -dumpaliases() -{ - size_t n; - - for (n = 0; n < naliases; n++) { - if (aliases[n].val == -1) - continue; - - switch (aliases[n].type) { - case HOST_ALIAS: - (void) puts("HOST_ALIAS"); - break; - - case CMND_ALIAS: - (void) puts("CMND_ALIAS"); - break; - - case USER_ALIAS: - (void) puts("USER_ALIAS"); - break; - - case RUNAS_ALIAS: - (void) puts("RUNAS_ALIAS"); - break; - } - (void) printf("\t%s: %d\n", aliases[n].name, aliases[n].val); - } -} - -/* - * Lists the contents of cm_list and ga_list for `sudo -l'. - */ -void -list_matches() -{ - size_t count; - char *p; - struct generic_alias *ga, key; - - (void) printf("User %s may run the following commands on this host:\n", - user_name); - for (count = 0; count < cm_list_len; count++) { - - /* Print the runas list. */ - (void) fputs(" ", stdout); - if (cm_list[count].runas) { - (void) putchar('('); - p = strtok(cm_list[count].runas, ", "); - do { - if (p != cm_list[count].runas) - (void) fputs(", ", stdout); - - key.alias = p; - key.type = RUNAS_ALIAS; - if ((ga = (struct generic_alias *) lfind((VOID *) &key, - (VOID *) &ga_list[0], &ga_list_len, sizeof(key), genaliascmp))) - (void) fputs(ga->entries, stdout); - else - (void) fputs(p, stdout); - } while ((p = strtok(NULL, ", "))); - (void) fputs(") ", stdout); - } else { - (void) printf("(%s) ", def_runas_default); - } - -#ifdef HAVE_SELINUX - /* SELinux role and type */ - if (cm_list[count].role != NULL) - (void) printf("ROLE=%s ", cm_list[count].role); - if (cm_list[count].type != NULL) - (void) printf("TYPE=%s ", cm_list[count].type); -#endif - - /* Is execve(2) disabled? */ - if (cm_list[count].noexecve == TRUE && !def_noexec) - (void) fputs("NOEXEC: ", stdout); - else if (cm_list[count].noexecve == FALSE && def_noexec) - (void) fputs("EXEC: ", stdout); - - /* Is a password required? */ - if (cm_list[count].nopasswd == TRUE && def_authenticate) - (void) fputs("NOPASSWD: ", stdout); - else if (cm_list[count].nopasswd == FALSE && !def_authenticate) - (void) fputs("PASSWD: ", stdout); - - /* Is setenv enabled? */ - if (cm_list[count].setenv == TRUE && !def_setenv) - (void) fputs("SETENV: ", stdout); - else if (cm_list[count].setenv == FALSE && def_setenv) - (void) fputs("NOSETENV: ", stdout); - - /* Print the actual command or expanded Cmnd_Alias. */ - key.alias = cm_list[count].cmnd; - key.type = CMND_ALIAS; - if ((ga = (struct generic_alias *) lfind((VOID *) &key, - (VOID *) &ga_list[0], &ga_list_len, sizeof(key), genaliascmp))) - (void) puts(ga->entries); - else - (void) puts(cm_list[count].cmnd); - } - - /* Be nice and free up space now that we are done. */ - for (count = 0; count < ga_list_len; count++) { - efree(ga_list[count].alias); - efree(ga_list[count].entries); - } - efree(ga_list); - ga_list = NULL; - - for (count = 0; count < cm_list_len; count++) { - efree(cm_list[count].runas); - efree(cm_list[count].cmnd); - efree(cm_list[count].role); - efree(cm_list[count].type); - } - efree(cm_list); - cm_list = NULL; - cm_list_len = 0; - cm_list_size = 0; -} - -/* - * Appends a source string to the destination, optionally prefixing a separator. - */ -static void -append(src, dstp, dst_len, dst_size, separator) - char *src, **dstp; - size_t *dst_len, *dst_size; - char *separator; -{ - size_t src_len = strlen(src); - char *dst = *dstp; - - /* - * Only add the separator if there is something to separate from. - * If the last char is a '!', don't apply the separator (XXX). - */ - if (separator && dst && dst[*dst_len - 1] != '!') - src_len += strlen(separator); - else - separator = NULL; - - /* Assumes dst will be NULL if not set. */ - if (dst == NULL) { - dst = (char *) emalloc(BUFSIZ); - *dst = '\0'; - *dst_size = BUFSIZ; - *dst_len = 0; - *dstp = dst; - } - - /* Allocate more space if necessary. */ - if (*dst_size <= *dst_len + src_len) { - while (*dst_size <= *dst_len + src_len) - *dst_size += BUFSIZ; - - dst = (char *) erealloc(dst, *dst_size); - *dstp = dst; - } - - /* Copy src -> dst adding a separator if appropriate and adjust len. */ - if (separator) - (void) strlcat(dst, separator, *dst_size); - (void) strlcat(dst, src, *dst_size); - *dst_len += src_len; -} - -/* - * Frees up space used by the aliases list and resets the associated counters. - */ -void -reset_aliases() -{ - size_t n; - - if (aliases) { - for (n = 0; n < naliases; n++) - efree(aliases[n].name); - efree(aliases); - aliases = NULL; - } - naliases = nslots = 0; -} - -/* - * Increments ga_list_len, allocating more space as necessary. - */ -static void -expand_ga_list() -{ - - if (++ga_list_len >= ga_list_size) { - while ((ga_list_size += STACKINCREMENT) < ga_list_len) - ; - ga_list = (struct generic_alias *) - erealloc3(ga_list, ga_list_size, sizeof(struct generic_alias)); - } - - ga_list[ga_list_len - 1].entries = NULL; -} - -/* - * Increments cm_list_len, allocating more space as necessary. - */ -static void -expand_match_list() -{ - - if (++cm_list_len >= cm_list_size) { - while ((cm_list_size += STACKINCREMENT) < cm_list_len) - ; - if (cm_list == NULL) - cm_list_len = 0; /* start at 0 since it is a subscript */ - cm_list = (struct command_match *) - erealloc3(cm_list, cm_list_size, sizeof(struct command_match)); - } - - cm_list[cm_list_len].runas = cm_list[cm_list_len].cmnd = NULL; - cm_list[cm_list_len].type = cm_list[cm_list_len].role = NULL; - cm_list[cm_list_len].nopasswd = FALSE; - cm_list[cm_list_len].noexecve = FALSE; - cm_list[cm_list_len].setenv = FALSE; -} - -/* - * Frees up spaced used by a previous parser run and allocates new space - * for various data structures. - */ -void -init_parser() -{ - - /* Free up old data structures if we run the parser more than once. */ - if (match) { - efree(match); - match = NULL; - top = 0; - parse_error = FALSE; - used_runas = FALSE; - errorlineno = -1; - sudolineno = 1; - } - - /* Allocate space for the matching stack. */ - stacksize = STACKINCREMENT; - match = (struct matchstack *) emalloc2(stacksize, sizeof(struct matchstack)); - - /* Allocate space for the match list (for `sudo -l'). */ - if (printmatches == TRUE) - expand_match_list(); -} -#line 1054 "sudo.tab.c" -/* allocate initial stack or double stack size, up to YYMAXDEPTH */ -#if defined(__cplusplus) || defined(__STDC__) -static int yygrowstack(void) -#else -static int yygrowstack() -#endif -{ - int newsize, i; - short *newss; - YYSTYPE *newvs; - - if ((newsize = yystacksize) == 0) - newsize = YYINITSTACKSIZE; - else if (newsize >= YYMAXDEPTH) - return -1; - else if ((newsize *= 2) > YYMAXDEPTH) - newsize = YYMAXDEPTH; - i = yyssp - yyss; -#ifdef SIZE_MAX -#define YY_SIZE_MAX SIZE_MAX -#else -#define YY_SIZE_MAX 0x7fffffff -#endif - if (newsize && YY_SIZE_MAX / newsize < sizeof *newss) - goto bail; - newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) : - (short *)malloc(newsize * sizeof *newss); /* overflow check above */ - if (newss == NULL) - goto bail; - yyss = newss; - yyssp = newss + i; - if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs) - goto bail; - newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) : - (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */ - if (newvs == NULL) - goto bail; - yyvs = newvs; - yyvsp = newvs + i; - yystacksize = newsize; - yysslim = yyss + newsize - 1; - return 0; -bail: - if (yyss) - free(yyss); - if (yyvs) - free(yyvs); - yyss = yyssp = NULL; - yyvs = yyvsp = NULL; - yystacksize = 0; - return -1; -} - -#define YYABORT goto yyabort -#define YYREJECT goto yyabort -#define YYACCEPT goto yyaccept -#define YYERROR goto yyerrlab -int -#if defined(__cplusplus) || defined(__STDC__) -yyparse(void) -#else -yyparse() -#endif -{ - int yym, yyn, yystate; -#if YYDEBUG -#if defined(__cplusplus) || defined(__STDC__) - const char *yys; -#else /* !(defined(__cplusplus) || defined(__STDC__)) */ - char *yys; -#endif /* !(defined(__cplusplus) || defined(__STDC__)) */ - - if ((yys = getenv("YYDEBUG"))) - { - yyn = *yys; - if (yyn >= '0' && yyn <= '9') - yydebug = yyn - '0'; - } -#endif /* YYDEBUG */ - - yynerrs = 0; - yyerrflag = 0; - yychar = (-1); - - if (yyss == NULL && yygrowstack()) goto yyoverflow; - yyssp = yyss; - yyvsp = yyvs; - *yyssp = yystate = 0; - -yyloop: - if ((yyn = yydefred[yystate]) != 0) goto yyreduce; - if (yychar < 0) - { - if ((yychar = yylex()) < 0) yychar = 0; -#if YYDEBUG - if (yydebug) - { - yys = 0; - if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; - if (!yys) yys = "illegal-symbol"; - printf("%sdebug: state %d, reading %d (%s)\n", - YYPREFIX, yystate, yychar, yys); - } -#endif - } - if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == yychar) - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: state %d, shifting to state %d\n", - YYPREFIX, yystate, yytable[yyn]); -#endif - if (yyssp >= yysslim && yygrowstack()) - { - goto yyoverflow; - } - *++yyssp = yystate = yytable[yyn]; - *++yyvsp = yylval; - yychar = (-1); - if (yyerrflag > 0) --yyerrflag; - goto yyloop; - } - if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == yychar) - { - yyn = yytable[yyn]; - goto yyreduce; - } - if (yyerrflag) goto yyinrecovery; -#if defined(lint) || defined(__GNUC__) - goto yynewerror; -#endif -yynewerror: - yyerror("syntax error"); -#if defined(lint) || defined(__GNUC__) - goto yyerrlab; -#endif -yyerrlab: - ++yynerrs; -yyinrecovery: - if (yyerrflag < 3) - { - yyerrflag = 3; - for (;;) - { - if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: state %d, error recovery shifting\ - to state %d\n", YYPREFIX, *yyssp, yytable[yyn]); -#endif - if (yyssp >= yysslim && yygrowstack()) - { - goto yyoverflow; - } - *++yyssp = yystate = yytable[yyn]; - *++yyvsp = yylval; - goto yyloop; - } - else - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: error recovery discarding state %d\n", - YYPREFIX, *yyssp); -#endif - if (yyssp <= yyss) goto yyabort; - --yyssp; - --yyvsp; - } - } - } - else - { - if (yychar == 0) goto yyabort; -#if YYDEBUG - if (yydebug) - { - yys = 0; - if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; - if (!yys) yys = "illegal-symbol"; - printf("%sdebug: state %d, error recovery discards token %d (%s)\n", - YYPREFIX, yystate, yychar, yys); - } -#endif - yychar = (-1); - goto yyloop; - } -yyreduce: -#if YYDEBUG - if (yydebug) - printf("%sdebug: state %d, reducing by rule %d (%s)\n", - YYPREFIX, yystate, yyn, yyrule[yyn]); -#endif - yym = yylen[yyn]; - yyval = yyvsp[1-yym]; - switch (yyn) - { -case 3: -#line 313 "parse.yacc" -{ ; } -break; -case 4: -#line 315 "parse.yacc" -{ yyerrok; } -break; -case 5: -#line 316 "parse.yacc" -{ push; } -break; -case 6: -#line 316 "parse.yacc" -{ - while (top && user_matches != TRUE) - pop; - } -break; -case 7: -#line 321 "parse.yacc" -{ ; } -break; -case 8: -#line 323 "parse.yacc" -{ ; } -break; -case 9: -#line 325 "parse.yacc" -{ ; } -break; -case 10: -#line 327 "parse.yacc" -{ ; } -break; -case 11: -#line 329 "parse.yacc" -{ ; } -break; -case 13: -#line 335 "parse.yacc" -{ - defaults_matches = TRUE; - } -break; -case 14: -#line 338 "parse.yacc" -{ push; } -break; -case 15: -#line 338 "parse.yacc" -{ - defaults_matches = user_matches; - pop; - } -break; -case 16: -#line 342 "parse.yacc" -{ push; } -break; -case 17: -#line 342 "parse.yacc" -{ - defaults_matches = yyvsp[0].BOOLEAN == TRUE; - pop; - } -break; -case 18: -#line 346 "parse.yacc" -{ push; } -break; -case 19: -#line 346 "parse.yacc" -{ - defaults_matches = host_matches; - pop; - } -break; -case 22: -#line 356 "parse.yacc" -{ - if (defaults_matches == TRUE && - !set_default(yyvsp[0].string, NULL, TRUE)) { - yyerror(NULL); - YYERROR; - } - efree(yyvsp[0].string); - } -break; -case 23: -#line 364 "parse.yacc" -{ - if (defaults_matches == TRUE && - !set_default(yyvsp[0].string, NULL, FALSE)) { - yyerror(NULL); - YYERROR; - } - efree(yyvsp[0].string); - } -break; -case 24: -#line 372 "parse.yacc" -{ - if (defaults_matches == TRUE && - !set_default(yyvsp[-2].string, yyvsp[0].string, TRUE)) { - yyerror(NULL); - YYERROR; - } - efree(yyvsp[-2].string); - efree(yyvsp[0].string); - } -break; -case 25: -#line 381 "parse.yacc" -{ - if (defaults_matches == TRUE && - !set_default(yyvsp[-2].string, yyvsp[0].string, '+')) { - yyerror(NULL); - YYERROR; - } - efree(yyvsp[-2].string); - efree(yyvsp[0].string); - } -break; -case 26: -#line 390 "parse.yacc" -{ - if (defaults_matches == TRUE && - !set_default(yyvsp[-2].string, yyvsp[0].string, '-')) { - yyerror(NULL); - YYERROR; - } - efree(yyvsp[-2].string); - efree(yyvsp[0].string); - } -break; -case 29: -#line 405 "parse.yacc" -{ - /* - * We already did a push if necessary in - * cmndspec so just reset some values so - * the next 'privilege' gets a clean slate. - */ - host_matches = UNSPEC; - runas_matches = UNSPEC; - no_passwd = def_authenticate ? UNSPEC : TRUE; - no_execve = def_noexec ? TRUE : UNSPEC; - setenv_ok = def_setenv ? TRUE : UNSPEC; -#ifdef HAVE_SELINUX - efree(match[top-1].role); - match[top-1].role = NULL; - efree(match[top-1].type); - match[top-1].type = NULL; -#endif - } -break; -case 30: -#line 425 "parse.yacc" -{ - SETMATCH(host_matches, yyvsp[0].BOOLEAN); - } -break; -case 31: -#line 428 "parse.yacc" -{ - SETNMATCH(host_matches, yyvsp[0].BOOLEAN); - } -break; -case 32: -#line 433 "parse.yacc" -{ - yyval.BOOLEAN = TRUE; - } -break; -case 33: -#line 436 "parse.yacc" -{ - if (addr_matches(yyvsp[0].string)) - yyval.BOOLEAN = TRUE; - else - yyval.BOOLEAN = NOMATCH; - efree(yyvsp[0].string); - } -break; -case 34: -#line 443 "parse.yacc" -{ - if (netgr_matches(yyvsp[0].string, user_host, user_shost, NULL)) - yyval.BOOLEAN = TRUE; - else - yyval.BOOLEAN = NOMATCH; - efree(yyvsp[0].string); - } -break; -case 35: -#line 450 "parse.yacc" -{ - if (hostname_matches(user_shost, user_host, yyvsp[0].string) == 0) - yyval.BOOLEAN = TRUE; - else - yyval.BOOLEAN = NOMATCH; - efree(yyvsp[0].string); - } -break; -case 36: -#line 457 "parse.yacc" -{ - aliasinfo *aip = find_alias(yyvsp[0].string, HOST_ALIAS); - - /* could be an all-caps hostname */ - if (aip) - yyval.BOOLEAN = aip->val; - else if (strcasecmp(user_shost, yyvsp[0].string) == 0) - yyval.BOOLEAN = TRUE; - else { - if (pedantic) { - (void) fprintf(stderr, - "%s: undeclared Host_Alias `%s' referenced near line %d\n", - (pedantic == 1) ? "Warning" : "Error", yyvsp[0].string, sudolineno); - if (pedantic > 1) { - yyerror(NULL); - YYERROR; - } - } - yyval.BOOLEAN = NOMATCH; - } - efree(yyvsp[0].string); - } -break; -case 39: -#line 485 "parse.yacc" -{ SETENV_RESET; } -break; -case 40: -#line 485 "parse.yacc" -{ -#ifdef HAVE_SELINUX - /* Replace inherited role/type as needed. */ - if (yyvsp[-2].seinfo.role != NULL) { - efree(match[top-1].role); - match[top-1].role = yyvsp[-2].seinfo.role; - } - if (yyvsp[-2].seinfo.type != NULL) { - efree(match[top-1].type); - match[top-1].type = yyvsp[-2].seinfo.type; - } -#endif - /* - * Push the entry onto the stack if it is worth - * saving and reset cmnd_matches for next cmnd. - * - * We need to save at least one entry on - * the stack so sudoers_lookup() can tell that - * the user was listed in sudoers. Also, we - * need to be able to tell whether or not a - * user was listed for this specific host. - * - * If keepall is set and the user matches then - * we need to keep entries around too... - */ - if (MATCHED(user_matches) && - MATCHED(host_matches) && - MATCHED(cmnd_matches) && - MATCHED(runas_matches)) - pushcp; - else if (MATCHED(user_matches) && (top == 1 || - (top == 2 && MATCHED(host_matches) && - !MATCHED(match[0].host)))) - pushcp; - else if (user_matches == TRUE && keepall) - pushcp; - - cmnd_matches = UNSPEC; - } -break; -case 41: -#line 526 "parse.yacc" -{ - SETMATCH(cmnd_matches, yyvsp[0].BOOLEAN); - } -break; -case 42: -#line 529 "parse.yacc" -{ - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries("!", ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_cmnd("!", NULL); - } - } -break; -case 43: -#line 537 "parse.yacc" -{ - SETNMATCH(cmnd_matches, yyvsp[0].BOOLEAN); - } -break; -case 44: -#line 542 "parse.yacc" -{ -#ifdef HAVE_SELINUX - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE && runas_matches == TRUE) - append_role(yyvsp[0].string, NULL); - yyval.string = yyvsp[0].string; -#else - free(yyvsp[0].string); - yyval.string = NULL; -#endif /* HAVE_SELINUX */ - } -break; -case 45: -#line 555 "parse.yacc" -{ -#ifdef HAVE_SELINUX - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE && runas_matches == TRUE) - append_type(yyvsp[0].string, NULL); - yyval.string = yyvsp[0].string; -#else - free(yyvsp[0].string); - yyval.string = NULL; -#endif /* HAVE_SELINUX */ - } -break; -case 46: -#line 568 "parse.yacc" -{ -#ifdef HAVE_SELINUX - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE && runas_matches == TRUE) { - /* Inherit role. */ - cm_list[cm_list_len].role = - estrdup(cm_list[cm_list_len-1].role); - cm_list[cm_list_len].role_len = - cm_list[cm_list_len-1].role_len; - cm_list[cm_list_len].role_size = - cm_list[cm_list_len-1].role_len + 1; - /* Inherit type. */ - cm_list[cm_list_len].type = - estrdup(cm_list[cm_list_len-1].type); - cm_list[cm_list_len].type_len = - cm_list[cm_list_len-1].type_len; - cm_list[cm_list_len].type_size = - cm_list[cm_list_len-1].type_len + 1; - } -#endif /* HAVE_SELINUX */ - yyval.seinfo.role = NULL; - yyval.seinfo.type = NULL; - } -break; -case 47: -#line 591 "parse.yacc" -{ -#ifdef HAVE_SELINUX - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE && runas_matches == TRUE) { - /* Inherit type. */ - cm_list[cm_list_len].type = - estrdup(cm_list[cm_list_len-1].type); - cm_list[cm_list_len].type_len = - cm_list[cm_list_len-1].type_len; - cm_list[cm_list_len].type_size = - cm_list[cm_list_len-1].type_len + 1; - } -#endif /* HAVE_SELINUX */ - yyval.seinfo.role = yyvsp[0].string; - yyval.seinfo.type = NULL; - } -break; -case 48: -#line 607 "parse.yacc" -{ -#ifdef HAVE_SELINUX - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE && runas_matches == TRUE) { - /* Inherit role. */ - cm_list[cm_list_len].role = - estrdup(cm_list[cm_list_len-1].role); - cm_list[cm_list_len].role_len = - cm_list[cm_list_len-1].role_len; - cm_list[cm_list_len].role_size = - cm_list[cm_list_len-1].role_len + 1; - } -#endif /* HAVE_SELINUX */ - yyval.seinfo.type = yyvsp[0].string; - yyval.seinfo.role = NULL; - } -break; -case 49: -#line 623 "parse.yacc" -{ - yyval.seinfo.role = yyvsp[-1].string; - yyval.seinfo.type = yyvsp[0].string; - } -break; -case 50: -#line 627 "parse.yacc" -{ - yyval.seinfo.type = yyvsp[-1].string; - yyval.seinfo.role = yyvsp[0].string; - } -break; -case 51: -#line 633 "parse.yacc" -{ - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) { - if (runas_matches == UNSPEC) { - cm_list[cm_list_len].runas_len = 0; - } else { - /* Inherit runas data. */ - cm_list[cm_list_len].runas = - estrdup(cm_list[cm_list_len-1].runas); - cm_list[cm_list_len].runas_len = - cm_list[cm_list_len-1].runas_len; - cm_list[cm_list_len].runas_size = - cm_list[cm_list_len-1].runas_len + 1; - } - } - /* - * If this is the first entry in a command list - * then check against default runas user. - */ - if (runas_matches == UNSPEC) { - runas_matches = userpw_matches(def_runas_default, - *user_runas, runas_pw) ? TRUE : NOMATCH; - } - } -break; -case 52: -#line 657 "parse.yacc" -{ - runas_matches = yyvsp[0].BOOLEAN; - } -break; -case 53: -#line 662 "parse.yacc" -{ ; } -break; -case 54: -#line 663 "parse.yacc" -{ - /* Later entries override earlier ones. */ - if (yyvsp[0].BOOLEAN != NOMATCH) - yyval.BOOLEAN = yyvsp[0].BOOLEAN; - else - yyval.BOOLEAN = yyvsp[-2].BOOLEAN; - } -break; -case 55: -#line 672 "parse.yacc" -{ ; } -break; -case 56: -#line 673 "parse.yacc" -{ - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries("!", ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas("!", ", "); - } - } -break; -case 57: -#line 681 "parse.yacc" -{ - /* Set $$ to the negation of runasuser */ - yyval.BOOLEAN = (yyvsp[0].BOOLEAN == NOMATCH ? NOMATCH : ! yyvsp[0].BOOLEAN); - } -break; -case 58: -#line 687 "parse.yacc" -{ - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries(yyvsp[0].string, ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas(yyvsp[0].string, ", "); - } - if (userpw_matches(yyvsp[0].string, *user_runas, runas_pw)) - yyval.BOOLEAN = TRUE; - else - yyval.BOOLEAN = NOMATCH; - efree(yyvsp[0].string); - used_runas = TRUE; - } -break; -case 59: -#line 702 "parse.yacc" -{ - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries(yyvsp[0].string, ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas(yyvsp[0].string, ", "); - } - if (usergr_matches(yyvsp[0].string, *user_runas, runas_pw)) - yyval.BOOLEAN = TRUE; - else - yyval.BOOLEAN = NOMATCH; - efree(yyvsp[0].string); - used_runas = TRUE; - } -break; -case 60: -#line 717 "parse.yacc" -{ - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries(yyvsp[0].string, ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas(yyvsp[0].string, ", "); - } - if (netgr_matches(yyvsp[0].string, NULL, NULL, *user_runas)) - yyval.BOOLEAN = TRUE; - else - yyval.BOOLEAN = NOMATCH; - efree(yyvsp[0].string); - used_runas = TRUE; - } -break; -case 61: -#line 732 "parse.yacc" -{ - aliasinfo *aip = find_alias(yyvsp[0].string, RUNAS_ALIAS); - - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries(yyvsp[0].string, ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas(yyvsp[0].string, ", "); - } - /* could be an all-caps username */ - if (aip) - yyval.BOOLEAN = aip->val; - else if (strcmp(yyvsp[0].string, *user_runas) == 0) - yyval.BOOLEAN = TRUE; - else { - if (pedantic) { - (void) fprintf(stderr, - "%s: undeclared Runas_Alias `%s' referenced near line %d\n", - (pedantic == 1) ? "Warning" : "Error", yyvsp[0].string, sudolineno); - if (pedantic > 1) { - yyerror(NULL); - YYERROR; - } - } - yyval.BOOLEAN = NOMATCH; - } - efree(yyvsp[0].string); - used_runas = TRUE; - } -break; -case 62: -#line 762 "parse.yacc" -{ - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries("ALL", ", "); - else if (host_matches == TRUE && - user_matches == TRUE) - append_runas("ALL", ", "); - } - yyval.BOOLEAN = TRUE; - } -break; -case 63: -#line 774 "parse.yacc" -{ - /* Inherit {NO,}{PASSWD,EXEC,SETENV} status. */ - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) { - if (no_passwd == TRUE) - cm_list[cm_list_len].nopasswd = TRUE; - else - cm_list[cm_list_len].nopasswd = FALSE; - if (no_execve == TRUE) - cm_list[cm_list_len].noexecve = TRUE; - else - cm_list[cm_list_len].noexecve = FALSE; - if (setenv_ok == TRUE) - cm_list[cm_list_len].setenv = TRUE; - else - cm_list[cm_list_len].setenv = FALSE; - } - } -break; -case 64: -#line 792 "parse.yacc" -{ - no_passwd = TRUE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].nopasswd = TRUE; - } -break; -case 65: -#line 798 "parse.yacc" -{ - no_passwd = FALSE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].nopasswd = FALSE; - } -break; -case 66: -#line 804 "parse.yacc" -{ - no_execve = TRUE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].noexecve = TRUE; - } -break; -case 67: -#line 810 "parse.yacc" -{ - no_execve = FALSE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].noexecve = FALSE; - } -break; -case 68: -#line 816 "parse.yacc" -{ - setenv_ok = TRUE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].setenv = TRUE; - } -break; -case 69: -#line 822 "parse.yacc" -{ - setenv_ok = FALSE; - if (printmatches == TRUE && host_matches == TRUE && - user_matches == TRUE) - cm_list[cm_list_len].setenv = FALSE; - } -break; -case 70: -#line 830 "parse.yacc" -{ - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries("ALL", ", "); - else if (host_matches == TRUE && - user_matches == TRUE) { - append_cmnd("ALL", NULL); - expand_match_list(); - } - } - /* sudo "ALL" implies the SETENV tag */ - if (setenv_ok == UNSPEC) - setenv_ok = IMPLIED; - - efree(safe_cmnd); - safe_cmnd = NULL; - yyval.BOOLEAN = TRUE; - } -break; -case 71: -#line 848 "parse.yacc" -{ - aliasinfo *aip; - - if (printmatches == TRUE) { - if (in_alias == TRUE) - append_entries(yyvsp[0].string, ", "); - else if (host_matches == TRUE && - user_matches == TRUE) { - append_cmnd(yyvsp[0].string, NULL); - expand_match_list(); - } - } - - if ((aip = find_alias(yyvsp[0].string, CMND_ALIAS))) - yyval.BOOLEAN = aip->val; - else { - if (pedantic) { - (void) fprintf(stderr, - "%s: undeclared Cmnd_Alias `%s' referenced near line %d\n", - (pedantic == 1) ? "Warning" : "Error", yyvsp[0].string, sudolineno); - if (pedantic > 1) { - yyerror(NULL); - YYERROR; - } - } - yyval.BOOLEAN = NOMATCH; - } - efree(yyvsp[0].string); - } -break; -case 72: -#line 877 "parse.yacc" -{ - if (printmatches == TRUE) { - if (in_alias == TRUE) { - append_entries(yyvsp[0].command.cmnd, ", "); - if (yyvsp[0].command.args) - append_entries(yyvsp[0].command.args, " "); - } - if (host_matches == TRUE && - user_matches == TRUE) { - append_cmnd(yyvsp[0].command.cmnd, NULL); - if (yyvsp[0].command.args) - append_cmnd(yyvsp[0].command.args, " "); - expand_match_list(); - } - } - - if (command_matches(yyvsp[0].command.cmnd, yyvsp[0].command.args)) - yyval.BOOLEAN = TRUE; - else - yyval.BOOLEAN = NOMATCH; - - efree(yyvsp[0].command.cmnd); - efree(yyvsp[0].command.args); - } -break; -case 75: -#line 907 "parse.yacc" -{ push; } -break; -case 76: -#line 907 "parse.yacc" -{ - if ((MATCHED(host_matches) || pedantic) && - !add_alias(yyvsp[-3].string, HOST_ALIAS, host_matches)) { - yyerror(NULL); - YYERROR; - } - pop; - } -break; -case 81: -#line 925 "parse.yacc" -{ - push; - if (printmatches == TRUE) { - in_alias = TRUE; - /* Allocate space for ga_list if necessary. */ - expand_ga_list(); - ga_list[ga_list_len-1].type = CMND_ALIAS; - ga_list[ga_list_len-1].alias = estrdup(yyvsp[0].string); - } - } -break; -case 82: -#line 934 "parse.yacc" -{ - if ((MATCHED(cmnd_matches) || pedantic) && - !add_alias(yyvsp[-3].string, CMND_ALIAS, cmnd_matches)) { - yyerror(NULL); - YYERROR; - } - pop; - efree(yyvsp[-3].string); - - if (printmatches == TRUE) - in_alias = FALSE; - } -break; -case 83: -#line 948 "parse.yacc" -{ ; } -break; -case 87: -#line 956 "parse.yacc" -{ - if (printmatches == TRUE) { - in_alias = TRUE; - /* Allocate space for ga_list if necessary. */ - expand_ga_list(); - ga_list[ga_list_len-1].type = RUNAS_ALIAS; - ga_list[ga_list_len-1].alias = estrdup(yyvsp[0].string); - } - } -break; -case 88: -#line 964 "parse.yacc" -{ - if ((yyvsp[0].BOOLEAN != NOMATCH || pedantic) && - !add_alias(yyvsp[-3].string, RUNAS_ALIAS, yyvsp[0].BOOLEAN)) { - yyerror(NULL); - YYERROR; - } - efree(yyvsp[-3].string); - - if (printmatches == TRUE) - in_alias = FALSE; - } -break; -case 91: -#line 981 "parse.yacc" -{ push; } -break; -case 92: -#line 981 "parse.yacc" -{ - if ((MATCHED(user_matches) || pedantic) && - !add_alias(yyvsp[-3].string, USER_ALIAS, user_matches)) { - yyerror(NULL); - YYERROR; - } - pop; - efree(yyvsp[-3].string); - } -break; -case 95: -#line 996 "parse.yacc" -{ - SETMATCH(user_matches, yyvsp[0].BOOLEAN); - } -break; -case 96: -#line 999 "parse.yacc" -{ - SETNMATCH(user_matches, yyvsp[0].BOOLEAN); - } -break; -case 97: -#line 1004 "parse.yacc" -{ - if (userpw_matches(yyvsp[0].string, user_name, sudo_user.pw)) - yyval.BOOLEAN = TRUE; - else - yyval.BOOLEAN = NOMATCH; - efree(yyvsp[0].string); - } -break; -case 98: -#line 1011 "parse.yacc" -{ - if (usergr_matches(yyvsp[0].string, user_name, sudo_user.pw)) - yyval.BOOLEAN = TRUE; - else - yyval.BOOLEAN = NOMATCH; - efree(yyvsp[0].string); - } -break; -case 99: -#line 1018 "parse.yacc" -{ - if (netgr_matches(yyvsp[0].string, NULL, NULL, user_name)) - yyval.BOOLEAN = TRUE; - else - yyval.BOOLEAN = NOMATCH; - efree(yyvsp[0].string); - } -break; -case 100: -#line 1025 "parse.yacc" -{ - aliasinfo *aip = find_alias(yyvsp[0].string, USER_ALIAS); - - /* could be an all-caps username */ - if (aip) - yyval.BOOLEAN = aip->val; - else if (strcmp(yyvsp[0].string, user_name) == 0) - yyval.BOOLEAN = TRUE; - else { - if (pedantic) { - (void) fprintf(stderr, - "%s: undeclared User_Alias `%s' referenced near line %d\n", - (pedantic == 1) ? "Warning" : "Error", yyvsp[0].string, sudolineno); - if (pedantic > 1) { - yyerror(NULL); - YYERROR; - } - } - yyval.BOOLEAN = NOMATCH; - } - efree(yyvsp[0].string); - } -break; -case 101: -#line 1047 "parse.yacc" -{ - yyval.BOOLEAN = TRUE; - } -break; -#line 2149 "sudo.tab.c" - } - yyssp -= yym; - yystate = *yyssp; - yyvsp -= yym; - yym = yylhs[yyn]; - if (yystate == 0 && yym == 0) - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: after reduction, shifting from state 0 to\ - state %d\n", YYPREFIX, YYFINAL); -#endif - yystate = YYFINAL; - *++yyssp = YYFINAL; - *++yyvsp = yyval; - if (yychar < 0) - { - if ((yychar = yylex()) < 0) yychar = 0; -#if YYDEBUG - if (yydebug) - { - yys = 0; - if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; - if (!yys) yys = "illegal-symbol"; - printf("%sdebug: state %d, reading %d (%s)\n", - YYPREFIX, YYFINAL, yychar, yys); - } -#endif - } - if (yychar == 0) goto yyaccept; - goto yyloop; - } - if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == yystate) - yystate = yytable[yyn]; - else - yystate = yydgoto[yym]; -#if YYDEBUG - if (yydebug) - printf("%sdebug: after reduction, shifting from state %d \ -to state %d\n", YYPREFIX, *yyssp, yystate); -#endif - if (yyssp >= yysslim && yygrowstack()) - { - goto yyoverflow; - } - *++yyssp = yystate; - *++yyvsp = yyval; - goto yyloop; -yyoverflow: - yyerror("yacc stack overflow"); -yyabort: - if (yyss) - free(yyss); - if (yyvs) - free(yyvs); - yyss = yyssp = NULL; - yyvs = yyvsp = NULL; - yystacksize = 0; - return (1); -yyaccept: - if (yyss) - free(yyss); - if (yyvs) - free(yyvs); - yyss = yyssp = NULL; - yyvs = yyvsp = NULL; - yystacksize = 0; - return (0); -} diff --git a/sudo.tab.h b/sudo.tab.h deleted file mode 100644 index ba97b3a..0000000 --- a/sudo.tab.h +++ /dev/null @@ -1,38 +0,0 @@ -#define COMMAND 257 -#define ALIAS 258 -#define DEFVAR 259 -#define NTWKADDR 260 -#define NETGROUP 261 -#define USERGROUP 262 -#define WORD 263 -#define DEFAULTS 264 -#define DEFAULTS_HOST 265 -#define DEFAULTS_USER 266 -#define DEFAULTS_RUNAS 267 -#define RUNAS 268 -#define NOPASSWD 269 -#define PASSWD 270 -#define NOEXEC 271 -#define EXEC 272 -#define SETENV 273 -#define NOSETENV 274 -#define ALL 275 -#define COMMENT 276 -#define HOSTALIAS 277 -#define CMNDALIAS 278 -#define USERALIAS 279 -#define RUNASALIAS 280 -#define ERROR 281 -#define TYPE 282 -#define ROLE 283 -#ifndef YYSTYPE_DEFINED -#define YYSTYPE_DEFINED -typedef union { - char *string; - int BOOLEAN; - struct sudo_command command; - int tok; - struct selinux_info seinfo; -} YYSTYPE; -#endif /* YYSTYPE_DEFINED */ -extern YYSTYPE yylval; diff --git a/sudo_edit.c b/sudo_edit.c index 5ed8e66..fba5a1b 100644 --- a/sudo_edit.c +++ b/sudo_edit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 Todd C. Miller + * Copyright (c) 2004-2008 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,14 +41,8 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #include -#include #include #include #include @@ -62,16 +56,19 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: sudo_edit.c,v 1.6.2.9 2008/06/21 00:47:52 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: sudo_edit.c,v 1.37 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ extern sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp; extern char **environ; +static char *find_editor(); + /* * Wrapper to allow users to edit privileged files with their own uid. */ -int sudo_edit(argc, argv, envp) +int +sudo_edit(argc, argv, envp) int argc; char **argv; char **envp; @@ -82,7 +79,6 @@ int sudo_edit(argc, argv, envp) char **nargv, **ap, *editor, *cp; char buf[BUFSIZ]; int error, i, ac, ofd, tfd, nargc, rval, tmplen, wasblank; - sigaction_t sa; struct stat sb; struct timespec ts1, ts2; struct tempfile { @@ -107,24 +103,25 @@ int sudo_edit(argc, argv, envp) while (tmplen > 0 && tmpdir[tmplen - 1] == '/') tmplen--; + /* + * Close password, shadow, and group files before we try to open + * user-specified files to prevent the opening of things like /dev/fd/4 + */ + sudo_endpwent(); + sudo_endgrent(); + /* * For each file specified by the user, make a temporary version * and copy the contents of the original to it. */ tf = emalloc2(argc - 1, sizeof(*tf)); - memset(tf, 0, (argc - 1) * sizeof(*tf)); + zero_bytes(tf, (argc - 1) * sizeof(*tf)); for (i = 0, ap = argv + 1; i < argc - 1 && *ap != NULL; i++, ap++) { error = -1; set_perms(PERM_RUNAS); - - /* - * We close the password file before we try to open the user-specified - * path to prevent the opening of things like /dev/fd/4. - */ - endpwent(); if ((ofd = open(*ap, O_RDONLY, 0644)) != -1 || errno == ENOENT) { if (ofd == -1) { - memset(&sb, 0, sizeof(sb)); /* new file */ + zero_bytes(&sb, sizeof(sb)); /* new file */ error = 0; } else { #ifdef HAVE_FSTAT @@ -137,9 +134,9 @@ int sudo_edit(argc, argv, envp) set_perms(PERM_ROOT); if (error || (ofd != -1 && !S_ISREG(sb.st_mode))) { if (error) - warn("%s", *ap); + warning("%s", *ap); else - warnx("%s: not a regular file", *ap); + warningx("%s: not a regular file", *ap); if (ofd != -1) close(ofd); argc--; @@ -159,16 +156,16 @@ int sudo_edit(argc, argv, envp) tfd = mkstemp(tf[i].tfile); set_perms(PERM_ROOT); if (tfd == -1) { - warn("mkstemp"); + warning("mkstemp"); goto cleanup; } if (ofd != -1) { while ((nread = read(ofd, buf, sizeof(buf))) != 0) { if ((nwritten = write(tfd, buf, nread)) != nread) { if (nwritten == -1) - warn("%s", tf[i].tfile); + warning("%s", tf[i].tfile); else - warnx("%s: short write", tf[i].tfile); + warningx("%s: short write", tf[i].tfile); goto cleanup; } } @@ -194,20 +191,8 @@ int sudo_edit(argc, argv, envp) if (argc == 1) return(1); /* no files readable, you lose */ - /* - * Determine which editor to use. We don't bother restricting this - * based on def_env_editor or def_editor since the editor runs with - * the uid of the invoking user, not the runas (privileged) user. - */ environ = envp; - if (((editor = getenv("VISUAL")) != NULL && *editor != '\0') || - ((editor = getenv("EDITOR")) != NULL && *editor != '\0')) { - editor = estrdup(editor); - } else { - editor = estrdup(def_editor); - if ((cp = strchr(editor, ':')) != NULL) - *cp = '\0'; /* def_editor could be a path */ - } + editor = find_editor(); /* * Allocate space for the new argument vector and fill it in. @@ -232,9 +217,6 @@ int sudo_edit(argc, argv, envp) nargv[ac] = NULL; /* Allow the editor to be suspended. */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sa.sa_handler = SIG_DFL; (void) sigaction(SIGTSTP, &saved_sa_tstp, NULL); /* @@ -244,18 +226,16 @@ int sudo_edit(argc, argv, envp) gettime(&ts1); kidpid = fork(); if (kidpid == -1) { - warn("fork"); + warning("fork"); goto cleanup; } else if (kidpid == 0) { /* child */ (void) sigaction(SIGINT, &saved_sa_int, NULL); (void) sigaction(SIGQUIT, &saved_sa_quit, NULL); set_perms(PERM_FULL_USER); - endpwent(); - endgrent(); - closefrom(STDERR_FILENO + 1); + closefrom(def_closefrom + 1); execvp(nargv[0], nargv); - warn("unable to execute %s", nargv[0]); + warning("unable to execute %s", nargv[0]); _exit(127); } @@ -299,10 +279,10 @@ int sudo_edit(argc, argv, envp) set_perms(PERM_ROOT); if (error || !S_ISREG(sb.st_mode)) { if (error) - warn("%s", tf[i].tfile); + warning("%s", tf[i].tfile); else - warnx("%s: not a regular file", tf[i].tfile); - warnx("%s left unmodified", tf[i].ofile); + warningx("%s: not a regular file", tf[i].tfile); + warningx("%s left unmodified", tf[i].ofile); if (tfd != -1) close(tfd); continue; @@ -319,7 +299,7 @@ int sudo_edit(argc, argv, envp) timespecsub(&ts1, &ts2, &ts2); #endif if (timespecisset(&ts2)) { - warnx("%s unchanged", tf[i].ofile); + warningx("%s unchanged", tf[i].ofile); unlink(tf[i].tfile); close(tfd); continue; @@ -329,17 +309,17 @@ int sudo_edit(argc, argv, envp) ofd = open(tf[i].ofile, O_WRONLY|O_TRUNC|O_CREAT, 0644); set_perms(PERM_ROOT); if (ofd == -1) { - warn("unable to write to %s", tf[i].ofile); - warnx("contents of edit session left in %s", tf[i].tfile); + warning("unable to write to %s", tf[i].ofile); + warningx("contents of edit session left in %s", tf[i].tfile); close(tfd); continue; } while ((nread = read(tfd, buf, sizeof(buf))) > 0) { if ((nwritten = write(ofd, buf, nread)) != nread) { if (nwritten == -1) - warn("%s", tf[i].ofile); + warning("%s", tf[i].ofile); else - warnx("%s: short write", tf[i].ofile); + warningx("%s: short write", tf[i].ofile); break; } } @@ -347,11 +327,11 @@ int sudo_edit(argc, argv, envp) /* success, got EOF */ unlink(tf[i].tfile); } else if (nread < 0) { - warn("unable to read temporary file"); - warnx("contents of edit session left in %s", tf[i].tfile); + warning("unable to read temporary file"); + warningx("contents of edit session left in %s", tf[i].tfile); } else { - warn("unable to write to %s", tf[i].ofile); - warnx("contents of edit session left in %s", tf[i].tfile); + warning("unable to write to %s", tf[i].ofile); + warningx("contents of edit session left in %s", tf[i].tfile); } close(ofd); } @@ -365,3 +345,40 @@ cleanup: } return(1); } + +/* + * Determine which editor to use. We don't bother restricting this + * based on def_env_editor or def_editor since the editor runs with + * the uid of the invoking user, not the runas (privileged) user. + */ +static char * +find_editor() +{ + char *cp, *editor = NULL, **ev, *ev0[4]; + + ev0[0] = "SUDO_EDITOR"; + ev0[1] = "VISUAL"; + ev0[2] = "EDITOR"; + ev0[3] = NULL; + for (ev = ev0; *ev != NULL; ev++) { + if ((editor = getenv(*ev)) != NULL && *editor != '\0') { + if ((cp = strrchr(editor, '/')) != NULL) + cp++; + else + cp = editor; + /* Ignore "sudoedit" and "sudo" to avoid an endless loop. */ + if (strncmp(cp, "sudo", 4) != 0 || + (cp[4] != ' ' && cp[4] != '\0' && strcmp(cp + 4, "edit") != 0)) { + editor = estrdup(editor); + break; + } + } + editor = NULL; + } + if (editor == NULL) { + editor = estrdup(def_editor); + if ((cp = strchr(editor, ':')) != NULL) + *cp = '\0'; /* def_editor could be a path */ + } + return(editor); +} diff --git a/sudo_noexec.c b/sudo_noexec.c index f0723d0..084000a 100644 --- a/sudo_noexec.c +++ b/sudo_noexec.c @@ -29,7 +29,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: sudo_noexec.c,v 1.5.2.2 2007/06/12 00:56:43 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: sudo_noexec.c,v 1.12 2005/03/12 23:43:40 millert Exp $"; #endif /* lint */ /* diff --git a/sudo_nss.c b/sudo_nss.c new file mode 100644 index 0000000..7d70617 --- /dev/null +++ b/sudo_nss.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2007-2008 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 +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#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 $"; +#endif /* lint */ + +extern struct sudo_nss sudo_nss_file; +#ifdef HAVE_LDAP +extern struct sudo_nss sudo_nss_ldap; +#endif + +#if defined(HAVE_LDAP) && defined(_PATH_NSSWITCH_CONF) +/* + * Read in /etc/nsswitch.conf + * Returns a tail queue of matches. + */ +struct sudo_nss_list * +sudo_read_nss() +{ + FILE *fp; + char *cp; + int saw_files = FALSE; + int saw_ldap = FALSE; + int got_match = FALSE; + static struct sudo_nss_list snl; + + if ((fp = fopen(_PATH_NSSWITCH_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:", 8) != 0) + continue; + + /* Parse line */ + for ((cp = strtok(cp + 8, " \t")); cp != NULL; (cp = strtok(NULL, " \t"))) { + if (strcasecmp(cp, "files") == 0 && !saw_files) { + tq_append(&snl, &sudo_nss_file); + got_match = TRUE; + } else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) { + tq_append(&snl, &sudo_nss_ldap); + got_match = TRUE; + } else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) { + /* NOTFOUND affects the most recent entry */ + tq_last(&snl)->ret_notfound = TRUE; + got_match = FALSE; + } else + got_match = FALSE; + } + /* 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 /* HAVE_LDAP && _PATH_NSSWITCH_CONF */ + +/* + * Non-nsswitch.conf version with hard-coded order. + */ +struct sudo_nss_list * +sudo_read_nss() +{ + static struct sudo_nss_list snl; + +# ifdef HAVE_LDAP + tq_append(&snl, &sudo_nss_ldap); +# endif + tq_append(&snl, &sudo_nss_file); + + return(&snl); +} + +#endif /* HAVE_LDAP && _PATH_NSSWITCH_CONF */ + +/* Reset user_groups based on passwd entry. */ +static void +reset_groups(pw) + struct passwd *pw; +{ +#if defined(HAVE_INITGROUPS) && defined(HAVE_GETGROUPS) + if (pw != sudo_user.pw) { + (void) initgroups(pw->pw_name, pw->pw_gid); + if ((user_ngroups = getgroups(0, NULL)) > 0) { + user_groups = erealloc3(user_groups, user_ngroups, + sizeof(GETGROUPS_T)); + if (getgroups(user_ngroups, user_groups) < 0) + log_error(USE_ERRNO|MSG_ONLY, "can't get group vector"); + } else { + user_ngroups = 0; + efree(user_groups); + } + } +#endif +} + +/* + * Print out privileges for the specified user. + * We only get here if the user is allowed to run something on this host. + */ +void +display_privs(snl, pw) + struct sudo_nss_list *snl; + struct passwd *pw; +{ + struct sudo_nss *nss; + struct lbuf lbuf; + int count; + + /* Reset group vector so group matching works correctly. */ + reset_groups(pw); + + lbuf_init(&lbuf, NULL, 4, 0); + + /* Display defaults from all sources. */ + count = 0; + tq_foreach_fwd(snl, nss) + count += nss->display_defaults(nss, pw, &lbuf); + if (count) { + printf("Matching Defaults entries for %s on this host:\n", pw->pw_name); + lbuf_print(&lbuf); + putchar('\n'); + } + + /* Display Runas and Cmnd-specific defaults from all sources. */ + count = 0; + tq_foreach_fwd(snl, nss) + count += nss->display_bound_defaults(nss, pw, &lbuf); + if (count) { + printf("Runas and Command-specific defaults for %s:\n", pw->pw_name); + lbuf_print(&lbuf); + putchar('\n'); + } + + /* Display privileges from all sources. */ + printf("User %s may run the following commands on this host:\n", + pw->pw_name); + tq_foreach_fwd(snl, nss) + (void) nss->display_privs(nss, pw, &lbuf); + if (lbuf.len != 0) + lbuf_print(&lbuf); /* print remainder, if any */ + lbuf_destroy(&lbuf); +} + +/* + * Check user_cmnd against sudoers and print the matching entry if the + * command is allowed. + */ +int +display_cmnd(snl, pw) + struct sudo_nss_list *snl; + struct passwd *pw; +{ + struct sudo_nss *nss; + + /* Reset group vector so group matching works correctly. */ + reset_groups(pw); + + tq_foreach_fwd(snl, nss) { + if (nss->display_cmnd(nss, pw) == 0) + return(0); + } + return(1); +} diff --git a/sudo_nss.h b/sudo_nss.h new file mode 100644 index 0000000..361510f --- /dev/null +++ b/sudo_nss.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2007-2008 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. + * + * $Sudo: sudo_nss.h,v 1.5 2008/11/09 14:13:12 millert Exp $ + */ + +struct lbuf; +struct passwd; + +struct sudo_nss { + struct sudo_nss *prev; + struct sudo_nss *next; + int (*open) __P((struct sudo_nss *nss)); + int (*close) __P((struct sudo_nss *nss)); + int (*parse) __P((struct sudo_nss *nss)); + int (*setdefs) __P((struct sudo_nss *nss)); + int (*lookup) __P((struct sudo_nss *nss, int, int)); + int (*display_cmnd) __P((struct sudo_nss *nss, struct passwd *)); + int (*display_defaults) __P((struct sudo_nss *nss, struct passwd *, struct lbuf *)); + 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; +}; + +TQ_DECLARE(sudo_nss) + +struct sudo_nss_list *sudo_read_nss __P((void)); diff --git a/sudo_usage.h.in b/sudo_usage.h.in new file mode 100644 index 0000000..5a1bfc6 --- /dev/null +++ b/sudo_usage.h.in @@ -0,0 +1,13 @@ +#ifndef _SUDO_USAGE_H +#define _SUDO_USAGE_H + +/* + * 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 ..." + +#endif /* _SUDO_USAGE_H */ diff --git a/sudoers.cat b/sudoers.cat index 379c699..8c7876d 100644 --- a/sudoers.cat +++ b/sudoers.cat @@ -8,60 +8,60 @@ NNAAMMEE sudoers - list of which users may execute what DDEESSCCRRIIPPTTIIOONN - The _s_u_d_o_e_r_s file is composed of two types of entries: - aliases (basically variables) and user specifications - (which specify who may run what). + The _s_u_d_o_e_r_s file is composed of two types of entries: aliases + (basically variables) and user specifications (which specify who may + run what). - When multiple entries match for a user, they are applied - in order. Where there are multiple matches, the last - match is used (which is not necessarily the most specific - match). + When multiple entries match for a user, they are applied in order. + Where there are multiple matches, the last match is used (which is not + necessarily the most specific match). - The _s_u_d_o_e_r_s grammar will be described below in Extended - Backus-Naur Form (EBNF). Don't despair if you don't know - what EBNF is; it is fairly simple, and the definitions - below are annotated. + The _s_u_d_o_e_r_s grammar will be described below in Extended Backus-Naur + Form (EBNF). Don't despair if you don't know what EBNF is; it is + fairly simple, and the definitions below are annotated. QQuuiicckk gguuiiddee ttoo EEBBNNFF - EBNF is a concise and exact way of describing the grammar - of a language. Each EBNF definition is made up of _p_r_o_d_u_c_­ - _t_i_o_n _r_u_l_e_s. E.g., + EBNF is a concise and exact way of describing the grammar of a + language. Each EBNF definition is made up of _p_r_o_d_u_c_t_i_o_n _r_u_l_e_s. E.g., symbol ::= definition | alternate1 | alternate2 ... - Each _p_r_o_d_u_c_t_i_o_n _r_u_l_e references others and thus makes up a - grammar for the language. EBNF also contains the follow­ - ing operators, which many readers will recognize from reg­ - ular expressions. Do not, however, confuse them with - "wildcard" characters, which have different meanings. + Each _p_r_o_d_u_c_t_i_o_n _r_u_l_e references others and thus makes up a grammar for + the language. EBNF also contains the following operators, which many + readers will recognize from regular expressions. Do not, however, + confuse them with "wildcard" characters, which have different meanings. - ? Means that the preceding symbol (or group of symbols) - is optional. That is, it may appear once or not at - all. + ? Means that the preceding symbol (or group of symbols) is optional. + That is, it may appear once or not at all. - * Means that the preceding symbol (or group of symbols) - may appear zero or more times. + * Means that the preceding symbol (or group of symbols) may appear + zero or more times. - + Means that the preceding symbol (or group of symbols) - may appear one or more times. + + Means that the preceding symbol (or group of symbols) may appear + one or more times. - Parentheses may be used to group symbols together. For - clarity, we will use single quotes ('') to designate what - is a verbatim character string (as opposed to a symbol - name). + Parentheses may be used to group symbols together. For clarity, we + will use single quotes ('') to designate what is a verbatim character + string (as opposed to a symbol name). AAlliiaasseess - There are four kinds of aliases: User_Alias, Runas_Alias, - Host_Alias and Cmnd_Alias. + There are four kinds of aliases: User_Alias, Runas_Alias, Host_Alias + and Cmnd_Alias. + Alias ::= 'User_Alias' User_Alias (':' User_Alias)* | + 'Runas_Alias' Runas_Alias (':' Runas_Alias)* | + 'Host_Alias' Host_Alias (':' Host_Alias)* | + 'Cmnd_Alias' Cmnd_Alias (':' Cmnd_Alias)* + User_Alias ::= NAME '=' User_List + Runas_Alias ::= NAME '=' Runas_List -1.6.9p17 Jun 21, 2008 1 +1.7.0 December 3, 2008 1 @@ -70,14 +70,6 @@ DDEESSCCRRIIPPTTIIOONN SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - Alias ::= 'User_Alias' User_Alias (':' User_Alias)* | - 'Runas_Alias' Runas_Alias (':' Runas_Alias)* | - 'Host_Alias' Host_Alias (':' Host_Alias)* | - 'Cmnd_Alias' Cmnd_Alias (':' Cmnd_Alias)* - - User_Alias ::= NAME '=' User_List - - Runas_Alias ::= NAME '=' Runas_List Host_Alias ::= NAME '=' Host_List @@ -89,64 +81,61 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Alias_Type NAME = item1, item2, ... - where _A_l_i_a_s___T_y_p_e is one of User_Alias, Runas_Alias, - Host_Alias, or Cmnd_Alias. A NAME is a string of upper­ - case letters, numbers, and underscore characters ('_'). A - NAME mmuusstt start with an uppercase letter. It is possible - to put several alias definitions of the same type on a - single line, joined by a colon (':'). E.g., + where _A_l_i_a_s___T_y_p_e is one of User_Alias, Runas_Alias, Host_Alias, or + Cmnd_Alias. A NAME is a string of uppercase letters, numbers, and + underscore characters ('_'). A NAME mmuusstt start with an uppercase + letter. It is possible to put several alias definitions of the same + type on a single line, joined by a colon (':'). E.g., Alias_Type NAME = item1, item2, item3 : NAME = item4, item5 - The definitions of what constitutes a valid _a_l_i_a_s member - follow. + The definitions of what constitutes a valid _a_l_i_a_s member follow. User_List ::= User | User ',' User_List User ::= '!'* username | + '!'* '#'uid | '!'* '%'group | '!'* '+'netgroup | '!'* User_Alias - A User_List is made up of one or more usernames, system - groups (prefixed with '%'), netgroups (prefixed with '+') - and other aliases. Each list item may be prefixed with - one or more '!' operators. An odd number of '!' operators - negate the value of the item; an even number just cancel - each other out. + A User_List is made up of one or more usernames, uids (prefixed with + '#'), system groups (prefixed with '%'), netgroups (prefixed with '+') + and User_Aliases. 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. - Runas_List ::= Runas_User | - Runas_User ',' Runas_List + Runas_List ::= Runas_Member | + Runas_Member ',' Runas_List - Runas_User ::= '!'* username | - '!'* '#'uid | - '!'* '%'group | - '!'* +netgroup | - '!'* Runas_Alias + Runas_Member ::= '!'* username | + '!'* '#'uid | + '!'* '%'group | + '!'* +netgroup | + '!'* Runas_Alias + A Runas_List is similar to a User_List except that instead of + User_Aliases it can contain Runas_Aliases. Note that usernames and + groups are matched as strings. In other words, two users (groups) with + the same uid (gid) are considered to be distinct. If you wish to match + all usernames with the same uid (e.g. root and toor), you can use a uid + instead (#0 in the example given). + Host_List ::= Host | + Host ',' Host_List -1.6.9p17 Jun 21, 2008 2 +1.7.0 December 3, 2008 2 -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - A Runas_List is similar to a User_List except that it can - also contain uids (prefixed with '#') and instead of - User_Aliases it can contain Runas_Aliases. Note that - usernames and groups are matched as strings. In other - words, two users (groups) with the same uid (gid) are con­ - sidered to be distinct. If you wish to match all user­ - names with the same uid (e.g. root and toor), you can use - a uid instead (#0 in the example given). +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + - Host_List ::= Host | - Host ',' Host_List Host ::= '!'* hostname | '!'* ip_addr | @@ -154,21 +143,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) '!'* '+'netgroup | '!'* Host_Alias - A Host_List is made up of one or more hostnames, IP - addresses, network numbers, netgroups (prefixed with '+') - and other aliases. Again, the value of an item may be - negated with the '!' operator. If you do not specify a - netmask along with the network number, ssuuddoo will query - each of the local host's network interfaces and, if the - network number corresponds to one of the hosts's network - interfaces, the corresponding netmask will be used. The - netmask may be specified either in standard IP address - notation (e.g. 255.255.255.0 or ffff:ffff:ffff:ffff::), or - CIDR notation (number of bits, e.g. 24 or 64). A hostname - may include shell-style wildcards (see the Wildcards sec­ - tion below), but unless the hostname command on your - machine returns the fully qualified hostname, you'll need - to use the _f_q_d_n option for wildcards to be useful. + A Host_List is made up of one or more hostnames, IP addresses, network + numbers, netgroups (prefixed with '+') and other aliases. Again, the + value of an item may be negated with the '!' operator. If you do not + specify a netmask along with the network number, ssuuddoo will query each + of the local host's network interfaces and, if the network number + corresponds to one of the hosts's network interfaces, the corresponding + netmask will be used. The netmask may be specified either in standard + IP address notation (e.g. 255.255.255.0 or ffff:ffff:ffff:ffff::), or + CIDR notation (number of bits, e.g. 24 or 64). A hostname may include + shell-style wildcards (see the Wildcards section below), but unless the + hostname command on your machine returns the fully qualified hostname, + you'll need to use the _f_q_d_n option for wildcards to be useful. Cmnd_List ::= Cmnd | Cmnd ',' Cmnd_List @@ -182,53 +168,54 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) '!'* "sudoedit" | '!'* Cmnd_Alias - A Cmnd_List is a list of one or more commandnames, direc­ - tories, and other aliases. A commandname is a fully qual­ - ified 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 - 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 + A Cmnd_List is a list of one or more commandnames, directories, and + 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 + 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 + directory is a fully qualified pathname ending in a '/'. When you + specify a directory in a Cmnd_List, the user will be able to run any + file within that directory (but not in any subdirectories therein). + If a Cmnd has associated command line arguments, then the arguments in + the Cmnd must match exactly those given by the user on the command line + (or match the wildcards if there are any). Note that the following + characters must be escaped with a '\' if they are used in command + arguments: ',', ':', '=', '\'. The special command "sudoedit" is used + 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.6.9p17 Jun 21, 2008 3 -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) +1.7.0 December 3, 2008 3 + - wwiitthhoouutt command line arguments. A directory is a fully - qualified pathname ending in a '/'. When you specify a - directory in a Cmnd_List, the user will be able to run any - file within that directory (but not in any subdirectories - therein). - If a Cmnd has associated command line arguments, then the - arguments in the Cmnd must match exactly those given by - the user on the command line (or match the wildcards if - there are any). Note that the following characters must - be escaped with a '\' if they are used in command argu­ - ments: ',', ':', '=', '\'. The special command "sudoedit" - is used to permit a user to run ssuuddoo with the --ee flag (or - as ssuuddooeeddiitt). It may take command line arguments just as - a normal command does. + +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + DDeeffaauullttss - Certain configuration options may be changed from their - default values at runtime via one or more Default_Entry - lines. These may affect all users on any host, all users - on a specific host, a specific user, or commands being run - as a specific user. + Certain configuration options may be changed from their default values + at runtime via one or more Default_Entry lines. These may affect all + users on any host, all users on a specific host, a specific user, a + specific command, or commands being run as a specific user. Note that + per-command entries may not include command line arguments. If you + need to specify arguments, define a Cmnd_Alias and reference that + instead. Default_Type ::= 'Defaults' | 'Defaults' '@' Host_List | 'Defaults' ':' User_List | + 'Defaults' '!' Cmnd_List | 'Defaults' '>' Runas_List Default_Entry ::= Default_Type Parameter_List @@ -241,91 +228,104 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Parameter '-=' Value | '!'* Parameter - Parameters may be ffllaaggss, iinntteeggeerr values, ssttrriinnggss, or - lliissttss. Flags are implicitly boolean and can be turned off - via the '!' operator. Some integer, string and list - parameters may also be used in a boolean context to dis­ - able them. Values may be enclosed in double quotes (") - when they contain multiple words. Special characters may - be escaped with a backslash (\). + Parameters may be ffllaaggss, iinntteeggeerr values, ssttrriinnggss, or lliissttss. Flags are + implicitly boolean and can be turned off via the '!' operator. Some + integer, string and list parameters may also be used in a boolean + context to disable them. Values may be enclosed in double quotes (") + when they contain multiple words. Special characters may be escaped + with a backslash (\). - Lists have two additional assignment operators, += and -=. - These operators are used to add to and delete from a list - respectively. It is not an error to use the -= operator - to remove an element that does not exist in a list. + Lists have two additional assignment operators, += and -=. These + operators are used to add to and delete from a list respectively. It + is not an error to use the -= operator to remove an element that does + not exist in a list. - See "SUDOERS OPTIONS" for a list of supported Defaults - parameters. + 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 -1.6.9p17 Jun 21, 2008 4 + User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \ + (':' Host_List '=' Cmnd_Spec_List)* + 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 - UUsseerr SSppeecciiffiiccaattiioonn - User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \ - (':' Host_List '=' Cmnd_Spec_List)* - Cmnd_Spec_List ::= Cmnd_Spec | - Cmnd_Spec ',' Cmnd_Spec_List - Cmnd_Spec ::= Runas_Spec? Tag_Spec* Cmnd - Runas_Spec ::= '(' Runas_List ')' +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + + Tag_Spec ::= ('NOPASSWD:' | 'PASSWD:' | 'NOEXEC:' | 'EXEC:' | - 'SETENV:' | 'NOSETENV:') + 'SETENV:' | 'NOSETENV:' ) - A uusseerr ssppeecciiffiiccaattiioonn determines which commands a user may - run (and as what user) on specified hosts. By default, - commands are run as rroooott, but this can be changed on a - per-command basis. + A uusseerr ssppeecciiffiiccaattiioonn determines which commands a user may run (and as + 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: RRuunnaass__SSppeecc - A Runas_Spec is simply a Runas_List (as defined above) - enclosed in a set of parentheses. If you do not specify a - Runas_Spec in the user specification, a default Runas_Spec - of rroooott will be used. A Runas_Spec sets the default for - commands that follow it. What this means is that for the - entry: + A Runas_Spec determines the user and/or the group that a command may be + run as. A fully-specified Runas_Spec consists of two Runas_Lists (as + defined above) separated by a colon (':') and enclosed in a set of + parentheses. The first Runas_List indicates which users the command + may be run as via ssuuddoo's --uu option. The second defines a list of + groups that can be specified via ssuuddoo's --gg option. If both Runas_Lists + are specified, the command may be run with any combination of users and + groups listed in their respective Runas_Lists. If only the first is + specified, the command may be run as any user in the list but no --gg + option may be specified. If the first Runas_List is empty but the + second is specified, the command may be run as the invoking user with + the group set to any listed in the Runas_List. If no Runas_Spec is + specified the command may be run as rroooott and no group may be specified. + + A Runas_Spec sets the default for the commands that follow it. What + this means is that for the entry: dgb boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm - The user ddggbb may run _/_b_i_n_/_l_s, _/_b_i_n_/_k_i_l_l, and _/_u_s_r_/_b_i_n_/_l_p_r_m - -- but only as ooppeerraattoorr. E.g., + The user ddggbb may run _/_b_i_n_/_l_s, _/_b_i_n_/_k_i_l_l, and _/_u_s_r_/_b_i_n_/_l_p_r_m -- but only + as ooppeerraattoorr. E.g., $ sudo -u operator /bin/ls. - It is also possible to override a Runas_Spec later on in - an entry. If we modify the entry like so: + It is also possible to override a Runas_Spec later on in an entry. If + we modify the entry like so: 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 and _/_u_s_r_/_b_i_n_/_l_p_r_m as rroooott. + Then user ddggbb is now allowed to run _/_b_i_n_/_l_s as ooppeerraattoorr, but _/_b_i_n_/_k_i_l_l + and _/_u_s_r_/_b_i_n_/_l_p_r_m as rroooott. - TTaagg__SSppeecc + We can extend this to allow ddggbb to run /bin/ls with either the user or + group set to ooppeerraattoorr: + + dgb boulder = (operator : operator) /bin/ls, (root) /bin/kill, \ + /usr/bin/lprm + + In the following example, user ttccmm may run commands that access a modem + device file with the dialer group. Note that in this example only the + group will be set, the command still runs as user ttccmm. - A command may have zero or more tags associated with it. - There are six possible tag values, NOPASSWD, PASSWD, - NOEXEC, EXEC, SETENV and NOSETENV. Once a tag is set on a - Cmnd, subsequent Cmnds in the Cmnd_Spec_List, inherit the - tag unless it is overridden by the opposite tag (i.e.: - PASSWD overrides NOPASSWD and NOEXEC overrides EXEC). -1.6.9p17 Jun 21, 2008 5 +1.7.0 December 3, 2008 5 @@ -334,64 +334,64 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu, \ + /usr/local/bin/minicom + + TTaagg__SSppeecc + + A command may have zero or more tags associated with it. There are + eight possible tag values, NOPASSWD, PASSWD, NOEXEC, EXEC, SETENV and + NOSETENV. Once a tag is set on a Cmnd, subsequent Cmnds in the + Cmnd_Spec_List, inherit the tag unless it is overridden by the opposite + tag (i.e.: PASSWD overrides NOPASSWD and NOEXEC overrides EXEC). + _N_O_P_A_S_S_W_D _a_n_d _P_A_S_S_W_D - By default, ssuuddoo requires that a user authenticate him or - herself before running a command. This behavior can be - modified via the NOPASSWD tag. Like a Runas_Spec, the - NOPASSWD tag sets a default for the commands that follow - it in the Cmnd_Spec_List. Conversely, the PASSWD tag can - be used to reverse things. For example: + By default, ssuuddoo requires that a user authenticate him or herself + before running a command. This behavior can be modified via the + NOPASSWD tag. Like a Runas_Spec, the NOPASSWD tag sets a default for + the commands that follow it in the Cmnd_Spec_List. Conversely, the + PASSWD tag can be used to reverse things. For example: ray rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm - would allow the user rraayy to run _/_b_i_n_/_k_i_l_l, _/_b_i_n_/_l_s, and - _/_u_s_r_/_b_i_n_/_l_p_r_m as root on the machine rushmore as rroooott - without authenticating himself. If we only want rraayy to be - able to run _/_b_i_n_/_k_i_l_l without a password the entry would - be: + would allow the user rraayy to run _/_b_i_n_/_k_i_l_l, _/_b_i_n_/_l_s, and _/_u_s_r_/_b_i_n_/_l_p_r_m + as rroooott on the machine rushmore without authenticating himself. If we + only want rraayy to be able to run _/_b_i_n_/_k_i_l_l without a password the entry + would be: ray rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm - Note, however, that the PASSWD tag has no effect on users - who are in the group specified by the _e_x_e_m_p_t___g_r_o_u_p option. + Note, however, that the PASSWD tag has no effect on users who are in + the group specified by the _e_x_e_m_p_t___g_r_o_u_p option. - By default, if the NOPASSWD tag is applied to any of the - entries for a user on the current host, he or she will be - able to run sudo -l without a password. Additionally, a - user may only run sudo -v without a password if the - NOPASSWD tag is present for all a user's entries that per­ - tain to the current host. This behavior may be overridden - via the verifypw and listpw options. + By default, if the NOPASSWD tag is applied to any of the entries for a + user on the current host, he or she will be able to run sudo -l without + a password. Additionally, a user may only run sudo -v without a + password if the NOPASSWD tag is present for all a user's entries that + pertain to the current host. This behavior may be overridden via the + verifypw and listpw options. _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. + 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. + 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 - See the "PREVENTING SHELL ESCAPES" section below for more - details on how NOEXEC works and whether or not it will - work on your system. + 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 variables set on the command line - way are not subject to the restrictions imposed by - _e_n_v___c_h_e_c_k, _e_n_v___d_e_l_e_t_e, or _e_n_v___k_e_e_p. As such, only trusted - users should be allowed to set variables in this manner. -1.6.9p17 Jun 21, 2008 6 +1.7.0 December 3, 2008 6 @@ -400,17 +400,20 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - If the command matched is AALLLL, the SETENV tag is implied - for that command; this default may be overridden by use of - the UNSETENV tag. + 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 + variables set on the command line way are not subject to the + restrictions imposed by _e_n_v___c_h_e_c_k, _e_n_v___d_e_l_e_t_e, or _e_n_v___k_e_e_p. As such, + only trusted users should be allowed to set variables in this manner. + If the command matched is AALLLL, the SETENV tag is implied for that + command; this default may be overridden by use of the UNSETENV tag. WWiillddccaarrddss - ssuuddoo allows shell-style _w_i_l_d_c_a_r_d_s (aka meta or glob char­ - acters) to be used in pathnames as well as 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. + 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. * Matches any set of zero or more characters. @@ -420,14 +423,20 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) [!...] Matches any character nnoott in the specified range. - \x For any character "x", evaluates to "x". This is - used to escape special characters such as: "*", - "?", "[", and "}". + \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: + + /bin/ls [[\:alpha\:]]* - Note that a forward slash ('/') will nnoott be matched by - wildcards used in the pathname. When matching the command - line arguments, however, a slash ddooeess get matched by wild­ - cards. This is to make a path like: + Would match any filename beginning with a letter. + + Note that a forward slash ('/') will nnoott be matched by wildcards used + in the pathname. When matching the command line arguments, however, a + slash ddooeess get matched by wildcards. This is to make a path like: /usr/bin/* @@ -437,27 +446,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) The following exceptions apply to the above rules: - "" If the empty string "" is the only command line - argument in the _s_u_d_o_e_r_s entry it means that com­ - mand is not allowed to be run with aannyy arguments. - - OOtthheerr ssppeecciiaall cchhaarraacctteerrss aanndd rreesseerrvveedd wwoorrddss + "" If the empty string "" is the only command line argument in the + _s_u_d_o_e_r_s entry it means that command is not allowed to be run + with aannyy arguments. - The pound sign ('#') is used to indicate a comment (unless - it is part of a #include directive or unless it occurs in - the context of a user name and is followed by one or more - digits, in which case it is treated as a uid). Both the - comment character and any text after it, up to the end of - the line, are ignored. + IInncclluuddiinngg ootthheerr ffiilleess ffrroomm wwiitthhiinn ssuuddooeerrss - The reserved word AALLLL is a built-in _a_l_i_a_s that always - causes a match to succeed. It can be used wherever one - might otherwise use a Cmnd_Alias, User_Alias, Runas_Alias, - or Host_Alias. You should not try to define your own + 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 -1.6.9p17 Jun 21, 2008 7 +1.7.0 December 3, 2008 7 @@ -466,64 +466,64 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - _a_l_i_a_s called AALLLL as the built-in alias will be used in - preference to your own. Please note that using AALLLL can be - dangerous since in a command context, it allows the user - to run aannyy command on the system. + 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: - An exclamation point ('!') can be used as a logical _n_o_t - operator both in an _a_l_i_a_s and in front of a Cmnd. This - allows one to exclude certain values. Note, however, that - using a ! in conjunction with the built-in ALL alias to - allow a user to run "all but a few" commands rarely works - as intended (see SECURITY NOTES below). + #include /etc/sudoers.local - Long lines can be continued with a backslash ('\') as the - last character on the line. + 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. - Whitespace between elements in a list as well as special - syntactic characters in a _U_s_e_r _S_p_e_c_i_f_i_c_a_t_i_o_n ('=', ':', - '(', ')') is optional. + OOtthheerr ssppeecciiaall cchhaarraacctteerrss aanndd rreesseerrvveedd wwoorrddss - The following characters must be escaped with a backslash - ('\') when used as part of a word (e.g. a username or - hostname): '@', '!', '=', ':', ',', '(', ')', '\'. + The pound sign ('#') is used to indicate a comment (unless it is part + of a #include directive or unless it occurs in the context of a user + name and is followed by one or more digits, in which case it is treated + as a uid). Both the comment character and any text after it, up to the + end of the line, are ignored. + + The reserved word AALLLL is a built-in _a_l_i_a_s that always causes a match to + succeed. It can be used wherever one might otherwise use a Cmnd_Alias, + User_Alias, Runas_Alias, or Host_Alias. You should not try to define + your own _a_l_i_a_s called AALLLL as the built-in alias will be used in + preference to your own. Please note that using AALLLL can be dangerous + since in a command context, it allows the user to run aannyy command on + the system. + + An exclamation point ('!') can be used as a logical _n_o_t operator both + in an _a_l_i_a_s and in front of a Cmnd. This allows one to exclude certain + values. Note, however, that using a ! in conjunction with the built-in + ALL alias to allow a user to run "all but a few" commands rarely works + as intended (see SECURITY NOTES below). -SSUUDDOOEERRSS OOPPTTIIOONNSS - ssuuddoo's behavior can be modified by Default_Entry lines, as - explained earlier. A list of all supported Defaults - parameters, grouped by type, are listed below. + Long lines can be continued with a backslash ('\') as the last + character on the line. - FFllaaggss: + Whitespace between elements in a list as well as special syntactic + characters in a _U_s_e_r _S_p_e_c_i_f_i_c_a_t_i_o_n ('=', ':', '(', ')') is optional. - always_set_home If set, ssuuddoo will set the HOME environment - variable to the home directory of the tar­ - get user (which is root unless the --uu - option is used). This effectively means - that the --HH flag is always implied. This - flag is _o_f_f by default. + The following characters must be escaped with a backslash ('\') when + used as part of a word (e.g. a username or hostname): '@', '!', '=', + ':', ',', '(', ')', '\'. - authenticate If set, users must authenticate themselves - via a password (or other means of authen­ - tication) before they may run commands. - This default may be overridden via the - PASSWD and NOPASSWD tags. This flag is _o_n - by default. +SSUUDDOOEERRSS OOPPTTIIOONNSS + ssuuddoo's behavior can be modified by Default_Entry lines, as explained + earlier. A list of all supported Defaults parameters, grouped by type, + are listed below. - env_editor If set, vviissuuddoo will use the value of the - EDITOR or VISUAL environment variables - before falling back on the default editor - list. Note that this may create a secu­ - rity hole as it allows the user to run any - arbitrary command as root without logging. - A safer alternative is to place a colon- - separated list of editors in the editor - variable. vviissuuddoo will then only use the - EDITOR or VISUAL if they match a value + FFllaaggss: -1.6.9p17 Jun 21, 2008 8 +1.7.0 December 3, 2008 8 @@ -532,64 +532,64 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - specified in editor. This flag is _o_f_f by - default. + 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 + that the --HH option is always implied. This flag is _o_f_f + by default. - env_reset If set, ssuuddoo will reset the environment to - only contain the LOGNAME, SHELL, USER, - USERNAME and the SUDO_* variables. Any - variables in the caller's environment that - match the env_keep and env_check lists are - then added. The default contents of the - env_keep and env_check lists are displayed - when ssuuddoo is run by root with the _-_V - option. If ssuuddoo was compiled with the - SECURE_PATH option, its value will be used - for the PATH environment variable. This - flag is _o_n by default. + authenticate If set, users must authenticate themselves via a + password (or other means of authentication) before they + may run commands. This default may be overridden via + the PASSWD and NOPASSWD tags. This flag is _o_n by + default. - fqdn Set this flag if you want to put fully - qualified hostnames in the _s_u_d_o_e_r_s file. - I.e., instead of myhost you would use - myhost.mydomain.edu. You may still use - the short form if you wish (and even mix - the two). Beware that turning on _f_q_d_n - requires ssuuddoo to make DNS lookups which - may make ssuuddoo unusable if DNS stops work­ - ing (for example if the machine is not - plugged into the network). Also note that - you must use the host's official name as - DNS knows it. That is, you may not use a - host alias (CNAME entry) due to perfor­ - mance issues and the fact that there is no - way to get all aliases from DNS. If your - machine's hostname (as returned by the - hostname command) is already fully quali­ - fied you shouldn't need to set _f_q_d_n. This - flag is _o_f_f by default. + closefrom_override + If set, the user may use ssuuddoo's --CC option which + overrides the default starting point at which ssuuddoo + begins closing open file descriptors. This flag is _o_f_f + by default. - ignore_dot If set, ssuuddoo will ignore '.' or '' (cur­ - rent dir) in the PATH environment vari­ - able; the PATH itself is not modified. - This flag is _o_f_f by default. Currently, - while it is possible to set _i_g_n_o_r_e___d_o_t in - _s_u_d_o_e_r_s, its value is not used. This - option should be considered read-only (it - will be fixed in a future version of - ssuuddoo). + env_editor If set, vviissuuddoo will use the value of the EDITOR or + VISUAL environment variables before falling back on the + default editor list. Note that this may create a + security hole as it allows the user to run any + arbitrary command as root without logging. A safer + alternative is to place a colon-separated list of + editors in the editor variable. vviissuuddoo will then only + use the EDITOR or VISUAL if they match a value + specified in editor. This flag is _o_f_f by default. + + env_reset If set, ssuuddoo will reset the environment to only contain + the LOGNAME, SHELL, USER, USERNAME and the SUDO_* + variables. Any variables in the caller's environment + that match the env_keep and env_check lists are then + added. The default contents of the env_keep and + env_check lists are displayed when ssuuddoo is run by root + with the _-_V option. If the _s_e_c_u_r_e___p_a_t_h option is set, + its value will be used for the PATH environment + variable. This flag is _o_n by default. + + fqdn Set this flag if you want to put fully qualified + hostnames in the _s_u_d_o_e_r_s file. I.e., instead of myhost + you would use myhost.mydomain.edu. You may still use + the short form if you wish (and even mix the two). + Beware that turning on _f_q_d_n requires ssuuddoo to make DNS + lookups which may make ssuuddoo unusable if DNS stops + working (for example if the machine is not plugged into + the network). Also note that you must use the host's + official name as DNS knows it. That is, you may not + use a host alias (CNAME entry) due to performance + issues and the fact that there is no way to get all + aliases from DNS. If your machine's hostname (as + returned by the hostname command) is already fully + qualified you shouldn't need to set _f_q_d_n. This flag is + _o_f_f by default. - ignore_local_sudoers - If set via LDAP, parsing of _/_e_t_c_/_s_u_d_o_e_r_s - will be skipped. This is intended for - Enterprises that wish to prevent the usage - of local sudoers files so that only LDAP - is used. This thwarts the efforts of - rogue operators who would attempt to add - roles to _/_e_t_c_/_s_u_d_o_e_r_s. When this option -1.6.9p17 Jun 21, 2008 9 +1.7.0 December 3, 2008 9 @@ -598,196 +598,196 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - is present, _/_e_t_c_/_s_u_d_o_e_r_s does not even - need to exist. Since this 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 _o_f_f by default. + 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. - insults If set, ssuuddoo will insult users when they - enter an incorrect password. This flag is - _o_f_f by default. - - log_host If set, the hostname will be logged in the - (non-syslog) ssuuddoo log file. This flag is + ignore_local_sudoers + If set via LDAP, parsing of _/_e_t_c_/_s_u_d_o_e_r_s will be + skipped. This is intended for Enterprises that wish to + prevent the usage of local sudoers files so that only + LDAP is used. This thwarts the efforts of rogue + operators who would attempt to add roles to + _/_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 + 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 _o_f_f by default. - log_year If set, the four-digit year will be logged - in the (non-syslog) ssuuddoo log file. This - flag is _o_f_f by default. + insults If set, ssuuddoo will insult users when they enter an + incorrect password. This flag is _o_f_f by default. - long_otp_prompt When validating with a One Time Password - (OPT) scheme such as SS//KKeeyy or OOPPIIEE, a two- - line prompt is used to make it easier to - cut and paste the challenge to a local - window. It's not as pretty as the default - but some people find it more convenient. - This flag is _o_f_f by default. + log_host If set, the hostname will be logged in the (non-syslog) + ssuuddoo log file. This flag is _o_f_f by default. - mail_always Send mail to the _m_a_i_l_t_o user every time a - users runs ssuuddoo. This flag is _o_f_f by - default. + log_year If set, the four-digit year will be logged in the (non- + syslog) ssuuddoo log file. This flag is _o_f_f by default. - mail_badpass Send mail to the _m_a_i_l_t_o user if the user - running ssuuddoo does not enter the correct - password. This flag is _o_f_f by default. + long_otp_prompt When validating with a One Time Password (OPT) scheme + such as SS//KKeeyy or OOPPIIEE, a two-line prompt is used to + make it easier to cut and paste the challenge to a + local window. It's not as pretty as the default but + some people find it more convenient. This flag is _o_f_f + by default. - mail_no_host If set, mail will be sent to the _m_a_i_l_t_o - user if the invoking user exists in the - _s_u_d_o_e_r_s file, but is not allowed to run - commands on the current host. This flag - is _o_f_f by default. + mail_always Send mail to the _m_a_i_l_t_o user every time a users runs + ssuuddoo. This flag is _o_f_f by default. - mail_no_perms If set, mail will be sent to the _m_a_i_l_t_o - user if the invoking user is allowed to - use ssuuddoo but the command they are trying - is not listed in their _s_u_d_o_e_r_s file entry - or is explicitly denied. This flag is _o_f_f + mail_badpass Send mail to the _m_a_i_l_t_o user if the user running ssuuddoo + does not enter the correct password. This flag is _o_f_f by default. - mail_no_user If set, mail will be sent to the _m_a_i_l_t_o - user if the invoking user is not in the - _s_u_d_o_e_r_s file. This flag is _o_n by default. + mail_no_host If set, mail will be sent to the _m_a_i_l_t_o user if the + invoking user exists in the _s_u_d_o_e_r_s file, but is not + allowed to run commands on the current host. This flag + is _o_f_f by default. - noexec If set, all commands run via ssuuddoo will - behave as if the NOEXEC tag has been set, + mail_no_perms If set, mail will be sent to the _m_a_i_l_t_o user if the + invoking user is allowed to use ssuuddoo but the command + they are trying is not listed in their _s_u_d_o_e_r_s file + entry or is explicitly denied. This flag is _o_f_f by + default. + mail_no_user If set, mail will be sent to the _m_a_i_l_t_o user if the + invoking user is not in the _s_u_d_o_e_r_s file. This flag is + _o_n by default. -1.6.9p17 Jun 21, 2008 10 +1.7.0 December 3, 2008 10 -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - 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 - well as the "PREVENTING SHELL ESCAPES" - section at the end of this manual. This - flag is _o_f_f by default. - path_info Normally, ssuuddoo will tell the user when a - command could not be found in their PATH - environment variable. Some sites may wish - to disable this as it could be used to - gather information on the location of exe­ - cutables that the normal user does not - have access to. The 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 flag is _o_n by default. + 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 + well as the "PREVENTING SHELL ESCAPES" section at the + end of this manual. This flag is _o_f_f by default. + + path_info Normally, ssuuddoo will tell the user when a command could + not be found in their PATH environment variable. Some + sites may wish to disable this as it could be used to + gather information on the location of executables that + the normal user does not have access to. The + disadvantage is that if the executable is simply not in + the user's PATH, ssuuddoo will tell the user that they are + not allowed to run it, which can be confusing. This + flag is _o_n by default. passprompt_override - The password prompt specified by - _p_a_s_s_p_r_o_m_p_t will normally only be used if - the passwod prompt provided by systems - such as PAM matches the string "Pass­ - word:". If _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 _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. - - requiretty If set, ssuuddoo will only run when the user - is logged in to a real tty. This will - disallow things like "rsh somehost sudo - ls" since _r_s_h(1) does not allocate a tty. - Because it is not possible to turn off - echo when there is no tty present, some - sites may wish to set this flag to prevent - a user from entering a visible password. + The password prompt specified by _p_a_s_s_p_r_o_m_p_t will + normally only be used if the passwod prompt provided by + systems such as PAM matches the string "Password:". If + _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 + _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. - root_sudo If set, root is allowed to run ssuuddoo too. - Disabling this prevents users from "chain­ - ing" ssuuddoo commands to get a root shell by - doing something like "sudo sudo /bin/sh". - Note, however, that turning off _r_o_o_t___s_u_d_o - will also prevent root and from running - ssuuddooeeddiitt. Disabling _r_o_o_t___s_u_d_o provides no - real additional security; it exists purely - for historical reasons. This flag is _o_n - + 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 + as _c_r_o_n(1m) or cgi-bin scripts. This flag is _o_f_f by + default. + root_sudo If set, root is allowed to run ssuuddoo too. Disabling + this prevents users from "chaining" ssuuddoo commands to + get a root shell by doing something like "sudo sudo + /bin/sh". Note, however, that turning off _r_o_o_t___s_u_d_o + will also prevent root and from running ssuuddooeeddiitt. + Disabling _r_o_o_t___s_u_d_o provides no real additional + security; it exists purely for historical reasons. + This flag is _o_n by default. + + rootpw If set, ssuuddoo will prompt for the root password instead + of the password of the invoking user. This flag is _o_f_f + by default. -1.6.9p17 Jun 21, 2008 11 + runaspw If set, ssuuddoo will prompt for the password of the user + defined by the _r_u_n_a_s___d_e_f_a_u_l_t option (defaults to root) + instead of the password of the invoking user. This + flag is _o_f_f by default. +1.7.0 December 3, 2008 11 -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - by default. - rootpw If set, ssuuddoo will prompt for the root - password instead of the password of the - invoking user. This flag is _o_f_f by - default. - runaspw If set, ssuuddoo will prompt for the password - of the user defined by the _r_u_n_a_s___d_e_f_a_u_l_t - option (defaults to root) instead of the - password of the invoking user. This flag - is _o_f_f by default. +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - set_home If set and ssuuddoo is invoked with the --ss - flag 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 - flag imply --HH. This flag is _o_f_f by - default. - set_logname Normally, ssuuddoo will set the LOGNAME, USER - and USERNAME environment variables to the - name of the target user (usually root - unless the --uu flag is given). However, - since some programs (including the RCS - revision control system) use LOGNAME to - determine the real identity of the user, - it may be desirable to change this behav­ - ior. This can be done by negating the - set_logname option. Note that if the - _e_n_v___r_e_s_e_t option has not been disabled, - entries in the _e_n_v___k_e_e_p list will override - the value of _s_e_t___l_o_g_n_a_m_e. This flag is + 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 + --HH. This flag is _o_f_f by default. + + set_logname Normally, ssuuddoo will set the LOGNAME, USER and USERNAME + environment variables to the name of the target user + (usually root unless the --uu option is given). However, + since some programs (including the RCS revision control + system) use LOGNAME to determine the real identity of + the user, it may be desirable to change this behavior. + This can be done by negating the set_logname option. + Note that if the _e_n_v___r_e_s_e_t option has not been + disabled, entries in the _e_n_v___k_e_e_p list will override + the value of _s_e_t___l_o_g_n_a_m_e. This flag is _o_f_f by default. + + setenv Allow the user to disable the _e_n_v___r_e_s_e_t option from the + command line. Additionally, environment variables set + via the command line are not subject to the + restrictions imposed by _e_n_v___c_h_e_c_k, _e_n_v___d_e_l_e_t_e, or + _e_n_v___k_e_e_p. As such, only trusted users should be + allowed to set variables in this manner. This flag is _o_f_f by default. - setenv Allow the user to disable the _e_n_v___r_e_s_e_t - option from the command line. Addition­ - ally, environment variables set via the - command line are not subject to the - restrictions imposed by _e_n_v___c_h_e_c_k, - _e_n_v___d_e_l_e_t_e, or _e_n_v___k_e_e_p. As such, only - trusted users should be allowed to set - variables in this manner. This flag is + shell_noargs If set and ssuuddoo is invoked with no arguments it acts as + if the --ss option had been given. That is, it runs a + shell as root (the shell is determined by the SHELL + environment variable if it is set, falling back on the + shell listed in the invoking user's /etc/passwd entry + if not). This flag is _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 + the real UID is left as the invoking user's UID. In + other words, this makes ssuuddoo act as a setuid wrapper. + This can be useful on systems that disable some + potentially dangerous functionality when a program is + run setuid. This option is only effective on systems + 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. - shell_noargs If set and ssuuddoo is invoked with no argu­ - ments it acts as if the --ss flag had been - given. That is, it runs a shell as root - (the shell is determined by the SHELL - environment variable if it is set, falling - back on the shell listed in the invoking - user's /etc/passwd entry if not). This - flag is _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.6.9p17 Jun 21, 2008 12 +1.7.0 December 3, 2008 12 @@ -796,64 +796,64 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - 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 the - real UID is left as the invoking user's - UID. In other words, this makes ssuuddoo act - as a setuid wrapper. This can be useful - on systems that disable some potentially - dangerous functionality when a program is - run setuid. This option is only effective - on systems 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. + user is logged in on in that directory. This flag is + _o_f_f by default. - targetpw If set, ssuuddoo will prompt for the password - of the user specified by the --uu flag - (defaults to root) instead of the password - of the invoking user. Note that this pre­ - cludes the use of a uid not listed in the - passwd database as an argument to the --uu - flag. This flag is _o_f_f by default. - - tty_tickets If set, users must authenticate on a per- - tty basis. Normally, ssuuddoo uses a direc­ - tory 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. - - use_loginclass If set, ssuuddoo will apply the defaults spec­ - ified for the target user's login class if - one exists. Only available if ssuuddoo is - configured with the --with-logincap - option. 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 + --with-logincap option. This flag is _o_f_f by default. + + visiblepw By default, ssuuddoo will refuse to run if the user must + enter a password but it is not possible to disable echo + on the terminal. If the _v_i_s_i_b_l_e_p_w flag is set, ssuuddoo + will prompt for a password even when it would be + visible on the screen. This makes it possible to run + things like "rsh somehost sudo ls" since _r_s_h(1) does + not allocate a tty. This flag is _o_f_f by default. IInntteeggeerrss: - passwd_tries The number of tries a user gets to enter - his/her password before ssuuddoo logs the - failure and exits. The default is 3. + closefrom Before it executes a command, ssuuddoo will close all open + file descriptors other than standard input, standard + output and standard error (ie: file descriptors 0-2). + The _c_l_o_s_e_f_r_o_m option can be used to specify a different + file descriptor at which to start closing. The default + is 3. + + passwd_tries The number of tries a user gets to enter his/her + password before ssuuddoo logs the failure and exits. The + default is 3. IInntteeggeerrss tthhaatt ccaann bbee uusseedd iinn aa bboooolleeaann ccoonntteexxtt: - loglinelen Number of characters per line for the file - log. This value is used to decide when to - wrap lines for nicer log files. This has - no effect on the syslog log file, only the - file log. The default is 80 (use 0 or - negate the option to disable word wrap). + loglinelen Number of characters per line for the file log. This + value is used to decide when to wrap lines for nicer + log files. This has no effect on the syslog log file, + only the file log. The default is 80 (use 0 or negate + the option to disable word wrap). - passwd_timeout Number of minutes before the ssuuddoo password - prompt times out. The default is 5; set - this to 0 for no password timeout. + passwd_timeout Number of minutes before the ssuuddoo password prompt times + out. The default is 5; set this to 0 for no password + timeout. + + timestamp_timeout + Number of minutes that can elapse before ssuuddoo will ask + for a passwd again. The default is 5. Set this to 0 + to always prompt for a password. If set to a value + less than 0 the user's timestamp will never expire. + This can be used to allow users to create or delete + their own timestamps via sudo -v and sudo -k + respectively. + umask Umask to use when running the command. Negate this + 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.6.9p17 Jun 21, 2008 13 + +1.7.0 December 3, 2008 13 @@ -862,196 +862,196 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - timestamp_timeout - Number of minutes that can elapse before - ssuuddoo will ask for a passwd again. The - default is 5. Set this to 0 to always - prompt for a password. If set to a value - less than 0 the user's timestamp will - never expire. This can be used to allow - users to create or delete their own times­ - tamps via sudo -v and sudo -k respec­ - tively. - - umask Umask to use when running the command. - Negate this option or set it to 0777 to - preserve the user's umask. The default is - 0022. + 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 + in _s_u_d_o_e_r_s. SSttrriinnggss: - badpass_message Message that is displayed if a user enters - an incorrect password. The default is - Sorry, try again. unless insults are - enabled. - - editor A colon (':') separated list of editors - allowed to be used with vviissuuddoo. vviissuuddoo - will choose the editor that matches the - user's EDITOR environment variable if pos­ - sible, or the first editor in the list - that exists and is executable. The - default is the path to vi on your system. - - mailsub Subject of the mail sent to the _m_a_i_l_t_o - user. The escape %h will expand to the - hostname of the machine. Default is *** - SECURITY information for %h ***. - - noexec_file Path to a shared library containing dummy - versions of the _e_x_e_c_v_(_), _e_x_e_c_v_e_(_) and _f_e_x_­ - _e_c_v_e_(_) library functions that just return - an error. This is used to implement the - _n_o_e_x_e_c functionality on systems that sup­ - port LD_PRELOAD or its equivalent. - Defaults to + badpass_message Message that is displayed if a user enters an incorrect + password. The default is Sorry, try again. unless + insults are enabled. + + editor A colon (':') separated list of editors allowed to be + used with vviissuuddoo. vviissuuddoo will choose the editor that + matches the user's EDITOR environment variable if + possible, or the first editor in the list that exists + and is executable. The default is the path to vi on + your system. + + mailsub Subject of the mail sent to the _m_a_i_l_t_o user. The escape + %h will expand to the hostname of the machine. Default + is *** SECURITY information for %h ***. + + noexec_file Path to a shared library containing dummy versions of + the _e_x_e_c_v_(_), _e_x_e_c_v_e_(_) and _f_e_x_e_c_v_e_(_) library functions + that just return an error. This is used to implement + the _n_o_e_x_e_c functionality on systems that support + LD_PRELOAD or its equivalent. Defaults to _/_u_s_r_/_l_o_c_a_l_/_l_i_b_e_x_e_c_/_s_u_d_o___n_o_e_x_e_c_._s_o. - passprompt The default prompt to use when asking for - a password; can be overridden via the --pp - option or the SUDO_PROMPT environment - variable. The following percent (`%') + passprompt The default prompt to use when asking for a password; + can be overridden via the --pp option or the SUDO_PROMPT + environment variable. The following percent (`%') escapes are supported: - %H expanded to the local hostname includ­ - ing the domain name (on if the - machine's hostname is fully qualified - + %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 option is set) + %h expanded to the local hostname without the domain + name -1.6.9p17 Jun 21, 2008 14 + %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 be run as (defaults to root) + %u expanded to the invoking user's login name + %% two consecutive % characters are collapsed into a + single % character + The default value is Password:. -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - or the _f_q_d_n option is set) +1.7.0 December 3, 2008 14 - %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 be run as (defaults - to root) - %u expanded to the invoking user's login - name - %% two consecutive % characters are col­ - lapsed into a single % character +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - The default value is Password:. - runas_default The default user to run commands as if the - --uu flag 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 + 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 before any Runas_Alias specifications. - syslog_badpri Syslog priority to use when user authenti­ - cates unsuccessfully. Defaults to alert. + syslog_badpri Syslog priority to use when user authenticates + unsuccessfully. Defaults to alert. - syslog_goodpri Syslog priority to use when user authenti­ - cates successfully. Defaults to notice. + syslog_goodpri Syslog priority to use when user authenticates + successfully. Defaults to notice. - timestampdir The directory in which ssuuddoo stores its - timestamp files. The default is - _/_v_a_r_/_r_u_n_/_s_u_d_o. + sudoers_locale Locale to use when parsing the sudoers file. Note that + changing the locale may affect how sudoers is + interpreted. Defaults to "C". - timestampowner The owner of the timestamp directory and - the timestamps stored therein. The - default is root. + timestampdir The directory in which ssuuddoo stores its timestamp files. + The default is _/_v_a_r_/_r_u_n_/_s_u_d_o. + + timestampowner The owner of the timestamp directory and the timestamps + stored therein. The default is root. SSttrriinnggss tthhaatt ccaann bbee uusseedd iinn aa bboooolleeaann ccoonntteexxtt: + askpass The _a_s_k_p_a_s_s option specifies the fully qualified path to a + helper program used to read the user's password when no + terminal is available. This may be the case when ssuuddoo is + executed from a graphical (as opposed to text-based) + application. The program specified by _a_s_k_p_a_s_s should + display the argument passed to it as the prompt and write + the user's password to the standard output. The value of + _a_s_k_p_a_s_s may be overridden by the SUDO_ASKPASS environment + 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. + 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: + 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. + never Never lecture the user. + once Only lecture the user the first time they run ssuuddoo. -1.6.9p17 Jun 21, 2008 15 +1.7.0 December 3, 2008 15 -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - never Never lecture the user. +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - 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. The default value - is _o_n_c_e. + 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. + The default value is _o_n_c_e. lecture_file - Path to a file containing an alternate ssuuddoo - lecture that will be used in place of the - standard lecture if the named file exists. By - default, ssuuddoo uses a built-in lecture. + Path to a file containing an alternate ssuuddoo lecture that + will be used in place of the standard lecture if the named + file exists. By default, ssuuddoo uses a built-in lecture. + + listpw This option controls when a password will be required when + a user runs ssuuddoo with the --ll option. It has the following + possible values: - listpw This option controls when a password will be - required when a user runs ssuuddoo with the --ll - flag. It has the following possible values: + all All the user's _s_u_d_o_e_r_s entries for the current host + must have the NOPASSWD flag set to avoid entering a + password. - all All the user's _s_u_d_o_e_r_s entries for the - current host must have the NOPASSWD - flag set to avoid entering a password. + always The user must always enter a password to use the --ll + option. - always The user must always enter a password - to use the --ll flag. + any At least one of the user's _s_u_d_o_e_r_s entries for the + current host must have the NOPASSWD flag set to + avoid entering a password. - any At least one of the user's _s_u_d_o_e_r_s - entries for the current host must have - the NOPASSWD flag set to avoid enter­ - ing a password. + never The user need never enter a password to use the --ll + option. - never The user need never enter a password - to use the --ll flag. + If no value is specified, a value of _a_n_y is implied. + Negating the option results in a value of _n_e_v_e_r being used. + The default value is _a_n_y. - If no value is specified, a value of _a_n_y is - implied. Negating the option results in a - value of _n_e_v_e_r being used. The default value - is _a_n_y. + logfile Path to the ssuuddoo log file (not the syslog log file). + Setting a path turns on logging to a file; negating this + option turns it off. By default, ssuuddoo logs via syslog. - logfile Path to the ssuuddoo log file (not the syslog log - file). Setting a path turns on logging to a - file; negating this option turns it off. By - default, ssuuddoo logs via syslog. + mailerflags Flags to use when invoking mailer. Defaults to --tt. - mailerflags Flags to use when invoking mailer. Defaults to - --tt. + mailerpath Path to mail program used to send warning mail. Defaults + to the path to sendmail found at configure time. - mailerpath Path to mail program used to send warning - mail. Defaults to the path to sendmail found - at configure time. + mailfrom Address to use for the "from" address when sending warning + and error mail. The address should be enclosed in double + quotes (") to protect against ssuuddoo interpreting the @ sign. + Defaults to the name of the user running ssuuddoo. - mailto Address to send warning and error mail to. - The address should be enclosed in double + mailto Address to send warning and error mail to. The address + should be enclosed in double quotes (") to protect against + ssuuddoo interpreting the @ sign. Defaults to root. + secure_path Path used for every command run from ssuuddoo. If you don't + trust the people running ssuuddoo to have a sane PATH + 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.6.9p17 Jun 21, 2008 16 + +1.7.0 December 3, 2008 16 @@ -1060,64 +1060,64 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - quotes (") to protect against ssuuddoo interpret­ - ing the @ sign. Defaults to root. + _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. - syslog Syslog facility if syslog is being used for - logging (negate to disable syslog logging). - Defaults to local2. + syslog Syslog facility if syslog is being used for logging (negate + to disable syslog logging). Defaults to local2. - verifypw This option controls when a password will be - required when a user runs ssuuddoo with the --vv - flag. It has the following possible values: + verifypw This option controls when a password will be required when + a user runs ssuuddoo with the --vv option. It has the following + possible values: - all All the user's _s_u_d_o_e_r_s entries for the - current host must have the NOPASSWD - flag set to avoid entering a password. + all All the user's _s_u_d_o_e_r_s entries for the current host + must have the NOPASSWD flag set to avoid entering a + password. - always The user must always enter a password - to use the --vv flag. + always The user must always enter a password to use the --vv + option. - any At least one of the user's _s_u_d_o_e_r_s - entries for the current host must have - the NOPASSWD flag set to avoid enter­ - ing a password. + any At least one of the user's _s_u_d_o_e_r_s entries for the + current host must have the NOPASSWD flag set to + avoid entering a password. - never The user need never enter a password - to use the --vv flag. + never The user need never enter a password to use the --vv + option. - If no value is specified, a value of _a_l_l is - implied. Negating the option results in a - value of _n_e_v_e_r being used. The default value - is _a_l_l. + If no value is specified, a value of _a_l_l is implied. + Negating the option results in a value of _n_e_v_e_r being used. + The default value is _a_l_l. LLiissttss tthhaatt ccaann bbee uusseedd iinn aa bboooolleeaann ccoonntteexxtt: - 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-style - format vulnerabilities in poorly-written - programs. The argument may be a dou­ - ble-quoted, space-separated list or a sin­ - gle value without double-quotes. The list - can be replaced, added to, deleted from, - or disabled by using the =, +=, -=, and ! - operators respectively. Regardless of - whether the env_reset option is enabled or - disabled, variables specified by env_check - will be preserved in the environment if - they pass the aforementioned check. The - default list of environment variables to - check is displayed when ssuuddoo is run by - root with the _-_V option. + 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- + style format vulnerabilities in poorly-written + programs. 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. Regardless of whether the env_reset + option is enabled or disabled, variables specified by + env_check will be preserved in the environment if they + pass the aforementioned check. The default list of + environment variables to check is displayed when ssuuddoo + is run by root with the _-_V option. - env_delete Environment variables to be removed from - the user's environment. The argument may + 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.6.9p17 Jun 21, 2008 17 +1.7.0 December 3, 2008 17 @@ -1126,39 +1126,26 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - 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. This allows fine- - grained control over the environment - ssuuddoo-spawned processes will receive. The - argument may be a double-quoted, space- - separated list or a single value without - double-quotes. The list can be replaced, - added to, deleted from, or disabled by - using the =, +=, -=, and ! operators - respectively. The default list of vari­ - ables to keep is displayed when ssuuddoo is - run by root with the _-_V option. - - When logging via _s_y_s_l_o_g(3), ssuuddoo accepts the following - values for the syslog facility (the value of the ssyysslloogg - Parameter): aauutthhpprriivv (if your OS supports it), aauutthh, ddaaee­­ - mmoonn, uusseerr, llooccaall00, llooccaall11, llooccaall22, llooccaall33, llooccaall44, llooccaall55, - llooccaall66, and llooccaall77. The following syslog priorities are - supported: aalleerrtt, ccrriitt, ddeebbuugg, eemmeerrgg, eerrrr, iinnffoo, nnoottiiccee, - and wwaarrnniinngg. + 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. + This allows fine-grained control over the environment + ssuuddoo-spawned processes will receive. The argument may + be a double-quoted, space-separated list or a single + value without double-quotes. The list can be replaced, + added to, deleted from, or disabled by using the =, +=, + -=, and ! operators respectively. The default list of + variables to keep is displayed when ssuuddoo is run by root + with the _-_V option. + + When logging via _s_y_s_l_o_g(3), ssuuddoo accepts the following values for the + syslog facility (the value of the ssyysslloogg Parameter): aauutthhpprriivv (if your + OS supports it), aauutthh, ddaaeemmoonn, uusseerr, llooccaall00, llooccaall11, llooccaall22, llooccaall33, + llooccaall44, llooccaall55, llooccaall66, and llooccaall77. The following syslog priorities + are supported: aalleerrtt, ccrriitt, ddeebbuugg, eemmeerrgg, eerrrr, iinnffoo, nnoottiiccee, and + wwaarrnniinngg. FFIILLEESS _/_e_t_c_/_s_u_d_o_e_r_s List of who can run what @@ -1168,29 +1155,8 @@ FFIILLEESS _/_e_t_c_/_n_e_t_g_r_o_u_p List of network groups EEXXAAMMPPLLEESS - Since the _s_u_d_o_e_r_s file is parsed in a single pass, order - is important. In general, you should structure _s_u_d_o_e_r_s - such that the Host_Alias, User_Alias, and Cmnd_Alias spec­ - ifications come first, followed by any Default_Entry - lines, and finally the Runas_Alias and user specifica­ - tions. The basic rule of thumb is you cannot reference an - Alias that has not already been defined. - - 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.6.9p17 Jun 21, 2008 18 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - + 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: # User alias specification User_Alias FULLTIMERS = millert, mikef, dowdy @@ -1214,6 +1180,18 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) # 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 @@ -1225,17 +1203,15 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Cmnd_Alias SU = /usr/bin/su Cmnd_Alias PAGERS = /usr/bin/more, /usr/bin/pg, /usr/bin/less - Here we override some of the compiled in default values. - We want ssuuddoo to log via _s_y_s_l_o_g(3) using the _a_u_t_h facility - in all cases. We don't want to subject the full time - staff to the ssuuddoo lecture, user mmiilllleerrtt need not give a - password, and we don't want to reset the LOGNAME, USER or - USERNAME environment variables when running commands as - root. Additionally, on the machines in the _S_E_R_V_E_R_S - Host_Alias, we keep an additional local log file and make - sure we log the year in each log line since the log - entries will be kept around for several years. Lastly, we - disable shell escapes for the commands in the PAGERS + Here we override some of the compiled in default values. We want ssuuddoo + to log via _s_y_s_l_o_g(3) using the _a_u_t_h facility in all cases. We don't + want to subject the full time staff to the ssuuddoo lecture, user mmiilllleerrtt + need not give a password, and we don't want to reset the LOGNAME, USER + or USERNAME environment variables when running commands as root. + Additionally, on the machines in the _S_E_R_V_E_R_S Host_Alias, we keep an + additional local log file and make sure we log the year in each log + line since the log entries will be kept around for several years. + Lastly, we disable shell escapes for the commands in the PAGERS Cmnd_Alias (_/_u_s_r_/_b_i_n_/_m_o_r_e, _/_u_s_r_/_b_i_n_/_p_g and _/_u_s_r_/_b_i_n_/_l_e_s_s). # Override built-in defaults @@ -1246,121 +1222,116 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Defaults@SERVERS log_year, logfile=/var/log/sudo.log 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 + what. + root ALL = (ALL) ALL + %wheel ALL = (ALL) ALL + We let rroooott and any user in group wwhheeeell run any command on any host as + any user. -1.6.9p17 Jun 21, 2008 19 + FULLTIMERS ALL = NOPASSWD: ALL + Full time sysadmins (mmiilllleerrtt, mmiikkeeff, and ddoowwddyy) may run any command on + any host without authenticating themselves. + PARTTIMERS ALL = ALL + Part time sysadmins (bboossttlleeyy, jjwwffooxx, and ccrraawwll) may run any command on + any host but they must authenticate themselves first (since the entry + lacks the NOPASSWD tag). + jack CSNETS = ALL -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 - The _U_s_e_r _s_p_e_c_i_f_i_c_a_t_i_o_n is the part that actually deter­ - mines who may run what. - root ALL = (ALL) ALL - %wheel ALL = (ALL) ALL +1.7.0 December 3, 2008 19 - We let rroooott and any user in group wwhheeeell run any command on - any host as any user. - FULLTIMERS ALL = NOPASSWD: ALL - Full time sysadmins (mmiilllleerrtt, mmiikkeeff, and ddoowwddyy) may run - any command on any host without authenticating themselves. - PARTTIMERS ALL = ALL - Part time sysadmins (bboossttlleeyy, jjwwffooxx, and ccrraawwll) may run - any command on any host but they must authenticate them­ - selves first (since the entry lacks the NOPASSWD tag). +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - jack CSNETS = ALL - 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 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. + 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. lisa CUNETS = ALL - The user lliissaa may run any command on any host in the - _C_U_N_E_T_S alias (the class B network 128.138.0.0). + The user lliissaa may run any command on any host in the _C_U_N_E_T_S alias (the + class B network 128.138.0.0). operator ALL = DUMPS, KILL, SHUTDOWN, HALT, REBOOT, PRINTING,\ sudoedit /etc/printcap, /usr/oper/bin/ - The ooppeerraattoorr user may run commands limited to simple main­ - tenance. Here, those are commands related to backups, - killing processes, the printing system, shutting down the - system, and any commands in the directory _/_u_s_r_/_o_p_e_r_/_b_i_n_/. + The ooppeerraattoorr user may run commands limited to simple maintenance. + Here, those are commands related to backups, killing processes, the + printing system, shutting down the system, and any commands in the + directory _/_u_s_r_/_o_p_e_r_/_b_i_n_/. joe ALL = /usr/bin/su operator The user jjooee may only _s_u(1) to operator. - pete HPPA = /usr/bin/passwd [A-z]*, !/usr/bin/passwd root + pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root - 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. + 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. 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 + listed in the _O_P Runas_Alias (rroooott and ooppeerraattoorr). + jim +biglab = ALL -1.6.9p17 Jun 21, 2008 20 + The user jjiimm may run any command on machines in the _b_i_g_l_a_b netgroup. + ssuuddoo knows that "biglab" is a netgroup due to the '+' prefix. + +secretaries ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser + Users in the sseeccrreettaarriieess netgroup need to help manage the printers as + well as add and remove users, so they are allowed to run those commands + on all machines. + fred ALL = (DB) NOPASSWD: ALL + The user ffrreedd can run commands as any user in the _D_B Runas_Alias + (oorraaccllee or ssyybbaassee) without giving a password. -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root* + On the _A_L_P_H_A machines, user jjoohhnn may su to anyone except root but he is + not allowed to specify any options to the _s_u(1) command. - The user bboobb may run anything on the _S_P_A_R_C and _S_G_I - machines as any user listed in the _O_P Runas_Alias (rroooott - and ooppeerraattoorr). + jen ALL, !SERVERS = ALL - jim +biglab = ALL - The user jjiimm may run any command on machines in the _b_i_g_l_a_b - netgroup. ssuuddoo knows that "biglab" is a netgroup due to - the '+' prefix. - +secretaries ALL = PRINTING, /usr/bin/adduser, /usr/bin/rmuser +1.7.0 December 3, 2008 20 - Users in the sseeccrreettaarriieess netgroup need to help manage the - printers as well as add and remove users, so they are - allowed to run those commands on all machines. - fred ALL = (DB) NOPASSWD: ALL - The user ffrreedd can run commands as any user in the _D_B - Runas_Alias (oorraaccllee or ssyybbaassee) without giving a password. - john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root* - On the _A_L_P_H_A machines, user jjoohhnn may su to anyone except - root but he is not allowed to give _s_u(1) any flags. +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - jen ALL, !SERVERS = ALL - 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). + 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). jill SERVERS = /usr/bin/, !SU, !SHELLS - For any machine in the _S_E_R_V_E_R_S Host_Alias, jjiillll may run - any commands in the directory _/_u_s_r_/_b_i_n_/ except for those - commands belonging to the _S_U and _S_H_E_L_L_S Cmnd_Aliases. + For any machine in the _S_E_R_V_E_R_S Host_Alias, jjiillll may run any commands in + the directory _/_u_s_r_/_b_i_n_/ except for those commands belonging to the _S_U + and _S_H_E_L_L_S Cmnd_Aliases. steve CSNETS = (operator) /usr/local/op_commands/ @@ -1369,85 +1340,48 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) matt valkyrie = KILL - On his personal workstation, valkyrie, mmaatttt needs to be - able to kill hung processes. + On his personal workstation, valkyrie, mmaatttt needs to be able to kill + hung processes. WEBMASTERS www = (www) ALL, (root) /usr/bin/su www - On the host www, any user in the _W_E_B_M_A_S_T_E_R_S User_Alias - (will, wendy, and wim), may run any command as user www - (which owns the web pages) or simply _s_u(1) to www. - - - - -1.6.9p17 Jun 21, 2008 21 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - + On the host www, any user in the _W_E_B_M_A_S_T_E_R_S User_Alias (will, wendy, + and wim), may run any command as user www (which owns the web pages) or + simply _s_u(1) to www. ALL CDROM = NOPASSWD: /sbin/umount /CDROM,\ /sbin/mount -o nosuid\,nodev /dev/cd0a /CDROM - Any user may mount or unmount a CD-ROM on the machines in - the CDROM Host_Alias (orion, perseus, hercules) without - entering a password. This is a bit tedious for users to - type, so it is a prime candidate for encapsulating in a - shell script. + Any user may mount or unmount a CD-ROM on the machines in the CDROM + Host_Alias (orion, perseus, hercules) without entering a password. + This is a bit tedious for users to type, so it is a prime candidate for + encapsulating in a shell script. SSEECCUURRIITTYY NNOOTTEESS - It is generally not effective to "subtract" commands from - ALL using the '!' operator. A user can trivially circum­ - vent this by copying the desired command to a different - name and then executing that. For example: + It is generally not effective to "subtract" commands from ALL using the + '!' operator. A user can trivially circumvent this by copying the + desired command to a different name and then executing that. For + example: bill ALL = ALL, !SU, !SHELLS - Doesn't really prevent bbiillll from running the commands - listed in _S_U or _S_H_E_L_L_S since he can simply copy those com­ - mands to a different name, or use a shell escape from an - editor or other program. Therefore, these kind of - restrictions should be considered advisory at best (and + Doesn't really prevent bbiillll from running the commands listed in _S_U or + _S_H_E_L_L_S since he can simply copy those commands to a different name, or + use a shell escape from an editor or other program. Therefore, these + kind of restrictions should be considered advisory at best (and reinforced by policy). PPRREEVVEENNTTIINNGG SSHHEELLLL EESSCCAAPPEESS - Once ssuuddoo executes a program, that program is free to do - whatever it pleases, including run other programs. This - can be a security issue since it is not uncommon for a - program to allow shell escapes, which lets a user bypass - ssuuddoo's access control and logging. Common programs that - permit shell escapes include shells (obviously), editors, + Once ssuuddoo executes a program, that program is free to do whatever it + pleases, including run other programs. This can be a security issue + since it is not uncommon for a program to allow shell escapes, which + lets a user bypass ssuuddoo's access control and logging. Common programs + that permit shell escapes include shells (obviously), editors, paginators, mail and terminal programs. - There are two basic approaches to this problem: - - restrict Avoid giving users access to commands that allow - the user to run arbitrary commands. Many edi­ - tors have a restricted mode where shell escapes - are disabled, though ssuuddooeeddiitt is a better solu­ - tion to running editors via ssuuddoo. Due to the - large number of programs that offer shell - escapes, restricting users to the set of pro­ - grams that do not if often unworkable. - noexec Many systems that support shared libraries have - the ability to override default library func­ - tions by pointing an environment variable (usu­ - ally LD_PRELOAD) to an alternate shared library. - On such systems, ssuuddoo's _n_o_e_x_e_c functionality can - be used to prevent a program run by ssuuddoo from - executing any other programs. Note, however, - that this applies only to native dynamically- - linked executables. Statically-linked executa­ - bles and foreign executables running under - - -1.6.9p17 Jun 21, 2008 22 +1.7.0 December 3, 2008 21 @@ -1456,64 +1390,64 @@ PPRREEVVEENNTTIINNGG SSHHEELLLL EESSCCAAPPEESS SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - binary emulation are not affected. + There are two basic approaches to this problem: - To tell whether or not ssuuddoo supports _n_o_e_x_e_c, you - can run the following as root: + restrict Avoid giving users access to commands that allow the user to + run arbitrary commands. Many editors have a restricted mode + where shell escapes are disabled, though ssuuddooeeddiitt is a better + solution to running editors via ssuuddoo. Due to the large + number of programs that offer shell escapes, restricting + users to the set of programs that do not if often unworkable. + + noexec Many systems that support shared libraries have the ability + to override default library functions by pointing an + environment variable (usually LD_PRELOAD) to an alternate + shared library. On such systems, ssuuddoo's _n_o_e_x_e_c functionality + can be used to prevent a program run by ssuuddoo from executing + any other programs. Note, however, that this applies only to + native dynamically-linked executables. Statically-linked + executables and foreign executables running under binary + emulation are not affected. + + To tell whether or not ssuuddoo supports _n_o_e_x_e_c, you can run the + following as root: sudo -V | grep "dummy exec" - If the resulting output contains a line that - begins with: + If the resulting output contains a line that begins with: File containing dummy exec functions: - then ssuuddoo may be able to replace the exec family - of functions in the standard library with its - own that simply return an error. Unfortunately, - there is no foolproof way to know whether or not - _n_o_e_x_e_c will work at compile-time. _n_o_e_x_e_c should - work on SunOS, Solaris, *BSD, Linux, IRIX, Tru64 - UNIX, MacOS X, and HP-UX 11.x. It is known nnoott - to work on AIX and UnixWare. _n_o_e_x_e_c is expected - to work on most operating systems that support - the LD_PRELOAD environment variable. Check your - operating system's manual pages for the dynamic - linker (usually ld.so, ld.so.1, dyld, dld.sl, - rld, or loader) to see if LD_PRELOAD is sup­ - ported. - - To enable _n_o_e_x_e_c for a command, use the NOEXEC - tag as documented in the User Specification sec­ - tion above. Here is that example again: + then ssuuddoo may be able to replace the exec family of functions + in the standard library with its own that simply return an + error. Unfortunately, there is no foolproof way to know + whether or not _n_o_e_x_e_c will work at compile-time. _n_o_e_x_e_c + should work on SunOS, Solaris, *BSD, Linux, IRIX, Tru64 UNIX, + MacOS X, and HP-UX 11.x. It is known nnoott to work on AIX and + UnixWare. _n_o_e_x_e_c is expected to work on most operating + systems that support the LD_PRELOAD environment variable. + Check your operating system's manual pages for the dynamic + linker (usually ld.so, ld.so.1, dyld, dld.sl, rld, or loader) + to see if LD_PRELOAD is supported. + + To enable _n_o_e_x_e_c for a command, use the NOEXEC tag as + documented in the User Specification section above. Here is + that example again: aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi - This allows user aaaarroonn to run _/_u_s_r_/_b_i_n_/_m_o_r_e and - _/_u_s_r_/_b_i_n_/_v_i with _n_o_e_x_e_c enabled. This will pre­ - vent those two commands from executing other - commands (such as a shell). If you are unsure - whether or not your system is capable of sup­ - porting _n_o_e_x_e_c you can always just try it out - and see if it works. - - Note that restricting shell escapes is not a panacea. - Programs running as root are still capable of many poten­ - tially hazardous operations (such as changing or overwrit­ - ing files) that could lead to unintended privilege escala­ - tion. In the specific case of an editor, a safer approach - is to give the user permission to run ssuuddooeeddiitt. + This allows user aaaarroonn to run _/_u_s_r_/_b_i_n_/_m_o_r_e and _/_u_s_r_/_b_i_n_/_v_i + with _n_o_e_x_e_c enabled. This will prevent those two commands + from executing other commands (such as a shell). If you are + unsure whether or not your system is capable of supporting + _n_o_e_x_e_c you can always just try it out and see if it works. -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) + Note that restricting shell escapes is not a panacea. Programs running + as root are still capable of many potentially hazardous operations -CCAAVVEEAATTSS - The _s_u_d_o_e_r_s file should aallwwaayyss be edited by the vviissuuddoo - command which locks the file and does grammatical - -1.6.9p17 Jun 21, 2008 23 +1.7.0 December 3, 2008 22 @@ -1522,39 +1456,39 @@ CCAAVVEEAATTSS SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - checking. It is imperative that _s_u_d_o_e_r_s be free of syntax - errors since ssuuddoo will not run with a syntactically incor­ - rect _s_u_d_o_e_r_s file. + (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) + +CCAAVVEEAATTSS + The _s_u_d_o_e_r_s file should aallwwaayyss be edited by the vviissuuddoo command which + locks the file and does grammatical checking. It is imperative that + _s_u_d_o_e_r_s be free of syntax errors since ssuuddoo will not run with a + syntactically incorrect _s_u_d_o_e_r_s file. - When using netgroups of machines (as opposed to users), if - you store fully qualified hostnames in the netgroup (as is - usually the case), you either need to have the machine's - hostname be fully qualified as returned by the hostname - command or use the _f_q_d_n option in _s_u_d_o_e_r_s. + When using netgroups of machines (as opposed to users), if you store + fully qualified hostnames in the netgroup (as is usually the case), you + either need to have the machine's hostname be fully qualified as + returned by the hostname command or use the _f_q_d_n option in _s_u_d_o_e_r_s. BBUUGGSS - If you feel you have found a bug in ssuuddoo, please submit a - bug report at http://www.sudo.ws/sudo/bugs/ + If you feel you have found a bug in ssuuddoo, please submit a bug report at + http://www.sudo.ws/sudo/bugs/ SSUUPPPPOORRTT - Limited free support is available via the sudo-users mail­ - ing list, see http://www.sudo.ws/mail­ - man/listinfo/sudo-users to subscribe or search the - archives. + Limited free support is available via the sudo-users mailing list, see + http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search + the archives. DDIISSCCLLAAIIMMEERR - ssuuddoo is provided ``AS IS'' and any express or implied war­ - ranties, including, but not limited to, the implied war­ - ranties of merchantability and fitness for a particular - purpose are disclaimed. See the LICENSE file distributed - with ssuuddoo or http://www.sudo.ws/sudo/license.html for com­ - plete details. - - - - - - + ssuuddoo is provided ``AS IS'' and any express or implied warranties, + including, but not limited to, the implied warranties of + merchantability and fitness for a particular purpose are disclaimed. + See the LICENSE file distributed with ssuuddoo or + http://www.sudo.ws/sudo/license.html for complete details. @@ -1579,6 +1513,6 @@ DDIISSCCLLAAIIMMEERR -1.6.9p17 Jun 21, 2008 24 +1.7.0 December 3, 2008 23 diff --git a/sudoers.ldap.cat b/sudoers.ldap.cat new file mode 100644 index 0000000..8b581ff --- /dev/null +++ b/sudoers.ldap.cat @@ -0,0 +1,792 @@ + + + +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) + + +NNAAMMEE + sudoers.ldap - sudo LDAP configuration + +DDEESSCCRRIIPPTTIIOONN + In addition to the standard _s_u_d_o_e_r_s file, ssuuddoo may be configured via + LAP. This can be especially useful for synchronizing _s_u_d_o_e_r_s in a + large, distributed environment. + + Using LDAP for _s_u_d_o_e_r_s has several benefits: + + +o ssuuddoo no longer needs to read _s_u_d_o_e_r_s in its entirety. When LDAP is + used, there are only two or three LDAP queries per invocation. + This makes it especially fast and particularly usable in LDAP + environments. + + +o ssuuddoo no longer exits if there is a typo in _s_u_d_o_e_r_s. It is not + possible to load LDAP data into the server that does not conform to + the sudoers schema, so proper syntax is guaranteed. It is still + possible to have typos in a user or host name, but this will not + prevent 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. + + +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. + + 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. + + For the most part, there is really no need for ssuuddoo-specific Aliases. + Unix groups or user netgroups can be used in place of User_Aliases and + RunasAliases. Host netgroups can be used in place of HostAliases. + Since Unix groups and netgroups can also be stored in LDAP there is no + real need for ssuuddoo-specific aliases. + + Cmnd_Aliases are not really required either since it is possible to + have multiple users listed in a sudoRole. Instead of defining a + Cmnd_Alias that is referenced by multiple users, one can create a + sudoRole that contains the commands and assign multiple users to it. + + SSUUDDOOeerrss LLDDAAPP ccoonnttaaiinneerr + + The _s_u_d_o_e_r_s configuration is contained in the ou=SUDOers LDAP + container. + + Sudo first looks for the cn=default entry in the SUDOers container. If + + + +1.7.0 October 24, 2008 1 + + + + + +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 + environment for all users. + + dn: cn=defaults,ou=SUDOers,dc=example,dc=com + objectClass: top + objectClass: sudoRole + cn: defaults + description: Default sudoOption's go here + sudoOption: env_keep+=SSH_AUTH_SOCK + + The equivalent of a sudoer in LDAP is a sudoRole. It consists of the + following components: + + ssuuddooUUsseerr + A user name, uid (prefixed with '#'), Unix group (prefixed with a + '%') or user netgroup (prefixed with a '+'). + + ssuuddooHHoosstt + A host name, IP address, IP network, or host netgroup (prefixed + with a '+'). The special value ALL will match any host. + + ssuuddooCCoommmmaanndd + A Unix command with optional command line arguments, potentially + including globbing characters (aka wild cards). The special value + ALL will match any command. If a command is prefixed with an + exclamation point '!', the user will be prohibited from running + that command. + + ssuuddooOOppttiioonn + Identical in function to the global options described above, but + specific to the sudoRole in which it resides. + + ssuuddooRRuunnAAssUUsseerr + A user name or uid (prefixed with '#') that commands may be run as + or a Unix group (prefixed with a '%') or user netgroup (prefixed + with a '+') that contains a list of users that commands may be run + as. The special value ALL will match any user. + + ssuuddooRRuunnAAssGGrroouupp + A Unix group or gid (prefixed with '#') that commands may be run + as. The special value ALL will match any group. + + Each component listed above should contain a single value, but there + may be multiple instances of each component type. A sudoRole must + contain at least one sudoUser, sudoHost and sudoCommand. + + The following example allows users in group wheel to run any command on + any host via ssuuddoo: + + + + + + + +1.7.0 October 24, 2008 2 + + + + + +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) + + + dn: cn=%wheel,ou=SUDOers,dc=example,dc=com + objectClass: top + objectClass: sudoRole + cn: %wheel + sudoUser: %wheel + sudoHost: ALL + sudoCommand: ALL + + AAnnaattoommyy ooff LLDDAAPP ssuuddooeerrss llooookkuupp + + When looking up a sudoer using LDAP there are only two or three LDAP + queries per invocation. The first query is to parse the global + options. The second is to match against the user's name and the groups + that the user belongs to. (The special ALL tag is matched in this + query too.) If no match is returned for the user's name and groups, a + third query returns all entries containing user netgroups and checks to + see if the user belongs to any of them. + + DDiiffffeerreenncceess bbeettwweeeenn LLDDAAPP aanndd nnoonn--LLDDAAPP ssuuddooeerrss + + There are some subtle differences in the way sudoers is handled once in + LDAP. Probably the biggest is that according to the RFC, LDAP ordering + is arbitrary and you cannot expect that Attributes and Entries are + returned in any specific order. If there are conflicting command rules + on an entry, the negative takes precedence. This is called paranoid + behavior (not necessarily the most specific match). + + Here is an example: + + # /etc/sudoers: + # Allow all commands except shell + johnny ALL=(root) ALL,!/bin/sh + # Always allows all commands because ALL is matched last + puddles ALL=(root) !/bin/sh,ALL + + # LDAP equivalent of johnny + # Allows all commands except shell + dn: cn=role1,ou=Sudoers,dc=my-domain,dc=com + objectClass: sudoRole + objectClass: top + cn: role1 + sudoUser: johnny + sudoHost: ALL + sudoCommand: ALL + sudoCommand: !/bin/sh + + # LDAP equivalent of puddles + # Notice that even though ALL comes last, it still behaves like + # role1 since the LDAP code assumes the more paranoid configuration + dn: cn=role2,ou=Sudoers,dc=my-domain,dc=com + objectClass: sudoRole + objectClass: top + cn: role2 + sudoUser: puddles + + + +1.7.0 October 24, 2008 3 + + + + + +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) + + + sudoHost: ALL + sudoCommand: !/bin/sh + sudoCommand: ALL + + Another difference is that negations on the Host, User or Runas are + currently ignorred. For example, the following attributes do not + behave the way one might expect. + + # does not match all but joe + # rather, does not match anyone + sudoUser: !joe + + # does not match all but joe + # rather, matches everyone including Joe + sudoUser: ALL + sudoUser: !joe + + # does not match all but web01 + # rather, matches all hosts including web01 + sudoHost: ALL + sudoHost: !web01 + + SSuuddooeerrss SScchheemmaa + + In order to use ssuuddoo's LDAP support, the ssuuddoo schema must be installed + on your LDAP server. In addition, be sure to index the 'sudoUser' + attribute. + + Three versions of the schema: one for OpenLDAP servers + (_s_c_h_e_m_a_._O_p_e_n_L_D_A_P), one for Netscape-derived servers (_s_c_h_e_m_a_._i_P_l_a_n_e_t), + and one for Microsoft Active Directory (_s_c_h_e_m_a_._A_c_t_i_v_e_D_i_r_e_c_t_o_r_y) may be + found in the ssuuddoo distribution. + + The schema for ssuuddoo in OpenLDAP form is included in the EXAMPLES + section. + + CCoonnffiigguurriinngg llddaapp..ccoonnff + + Sudo reads the _@_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 + 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. + + UURRII ldap[s]://[hostname[:port]] ... + Specifies a whitespace-delimited list of one or more URIs + + + +1.7.0 October 24, 2008 4 + + + + + +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) + + + describing the LDAP server(s) to connect to. The _p_r_o_t_o_c_o_l may be + either llddaapp or llddaappss, the latter being for servers that support TLS + (SSL) encryption. If no _p_o_r_t is specified, the default is port 389 + for ldap:// or port 636 for ldaps://. If no _h_o_s_t_n_a_m_e is specified, + ssuuddoo will connect to llooccaallhhoosstt. Only systems using the OpenSSL + libraries support the mixing of ldap:// and ldaps:// URIs. The + Netscape-derived libraries used on most commercial versions of Unix + are only capable of supporting one or the other. + + HHOOSSTT name[:port] ... + If no UURRII is specified, the HHOOSSTT parameter specifies a whitespace- + delimited list of LDAP servers to connect to. Each host may + include an optional _p_o_r_t separated by a colon (':'). The HHOOSSTT + parameter is deprecated in favor of the UURRII specification and is + included for backwards compatibility. + + PPOORRTT port_number + If no UURRII is specified, the PPOORRTT parameter specifies the default + port to connect to on the LDAP server if a HHOOSSTT parameter does not + specify the port itself. If no PPOORRTT parameter is used, the default + is port 389 for LDAP and port 636 for LDAP over TLS (SSL). The + PPOORRTT parameter is deprecated in favor of the UURRII specification and + is included for backwards compatibility. + + BBIINNDD__TTIIMMEELLIIMMIITT seconds + The BBIINNDD__TTIIMMEELLIIMMIITT parameter specifies the amount of time, in + seconds, to wait while trying to connect to an LDAP server. If + multiple UURRIIs or HHOOSSTTs are specified, this is the amount of time to + wait before trying the next one in the list. + + TTIIMMEELLIIMMIITT seconds + The TTIIMMEELLIIMMIITT parameter specifies the amount of time, in seconds, + to wait for a response to an LDAP query. + + SSUUDDOOEERRSS__BBAASSEE base + The base DN to use when performing ssuuddoo LDAP queries. Typically + this is of the form ou=SUDOers,dc=example,dc=com for the domain + example.com. + + SSUUDDOOEERRSS__DDEEBBUUGG debug_level + This sets the debug level for ssuuddoo LDAP queries. Debugging + information is printed to the standard error. A value of 1 results + in a moderate amount of debugging information. A value of 2 shows + the results of the matches themselves. This parameter should not + be set in a production environment as the extra information is + likely to confuse users. + + BBIINNDDDDNN DN + The BBIINNDDDDNN parameter specifies the identity, in the form of a + Distinguished Name (DN), to use when performing LDAP operations. + If not specified, LDAP operations are performed with an anonymous + identity. By default, most LDAP servers will allow anonymous + access. + + + + +1.7.0 October 24, 2008 5 + + + + + +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) + + + BBIINNDDPPWW secret + The BBIINNDDPPWW parameter specifies the password to use when performing + LDAP operations. This is typically used in conjunction with the + BBIINNDDDDNN parameter. + + RROOOOTTBBIINNDDDDNN DN + 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). + + LLDDAAPP__VVEERRSSIIOONN number + The version of the LDAP protocol to use when connecting to the + server. The default value is protocol version 3. + + SSSSLL on/true/yes/off/false/no + If the SSSSLL parameter is set to on, true or yes, TLS (SSL) + encryption is always used when communicating with the LDAP server. + Typically, this involves connecting to the server on port 636 + (ldaps). + + SSSSLL start_tls + If the SSSSLL parameter is set to start_tls, the LDAP server + connection is initiated normally and TLS encryption is begun before + the bind credentials are sent. This has the advantage of not + requiring a dedicated port for encrypted communications. This + parameter is only supported by LDAP servers that honor the + start_tls extension, such as the OpenLDAP server. + + TTLLSS__CCHHEECCKKPPEEEERR on/true/yes/off/false/no + If enabled, TTLLSS__CCHHEECCKKPPEEEERR will cause the LDAP server's TLS + certificated to be verified. If the server's TLS certificate + cannot be verified (usually because it is signed by an unknown + certificate authority), ssuuddoo will be unable to connect to it. If + TTLLSS__CCHHEECCKKPPEEEERR is disabled, no check is made. + + TTLLSS__CCAACCEERRTTFFIILLEE file name + The path to a certificate authority bundle which contains the + certificates for all the Certificate Authorities the client knows + to be valid, e.g. _/_e_t_c_/_s_s_l_/_c_a_-_b_u_n_d_l_e_._p_e_m. This option is only + supported by the OpenLDAP libraries. + + TTLLSS__CCAACCEERRTTDDIIRR directory + Similar to TTLLSS__CCAACCEERRTTFFIILLEE but instead of a file, it is a directory + containing individual Certificate Authority certificates, e.g. + _/_e_t_c_/_s_s_l_/_c_e_r_t_s. The directory specified by TTLLSS__CCAACCEERRTTDDIIRR is + checked after TTLLSS__CCAACCEERRTTFFIILLEE. This option is only supported by the + OpenLDAP libraries. + + TTLLSS__CCEERRTT file name + The path to a file containing the client certificate which can be + used to authenticate the client to the LDAP server. The + certificate type depends on the LDAP libraries used. + + + +1.7.0 October 24, 2008 6 + + + + + +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) + + + OpenLDAP: + tls_cert /etc/ssl/client_cert.pem + + Netscape-derived: + tls_cert /var/ldap/cert7.db + + When using Netscape-derived libraries, this file may also contain + Certificate Authority certificates. + + TTLLSS__KKEEYY file name + The path to a file containing the private key which matches the + certificate specified by TTLLSS__CCEERRTT. The private key must not be + password-protected. The key type depends on the LDAP libraries + used. + + OpenLDAP: + tls_key /etc/ssl/client_key.pem + + Netscape-derived: + tls_key /var/ldap/key3.db + + TTLLSS__RRAANNDDFFIILLEE file name + The TTLLSS__RRAANNDDFFIILLEE parameter specifies the path to an entropy source + for systems that lack a random device. It is generally used in + conjunction with _p_r_n_g_d or _e_g_d. This option is only supported by + the OpenLDAP libraries. + + TTLLSS__CCIIPPHHEERRSS cipher list + The TTLLSS__CCIIPPHHEERRSS parameter allows the administer to restrict which + encryption algorithms may be used for TLS (SSL) connections. See + the OpenSSL manual for a list of valid ciphers. This option is + only supported by the OpenLDAP libraries. + + UUSSEE__SSAASSLL on/true/yes/off/false/no + Enable UUSSEE__SSAASSLL for LDAP servers that support SASL authentication. + + SSAASSLL__AAUUTTHH__IIDD identity + The SASL user name to use when connecting to the LDAP server. By + default, ssuuddoo will use an anonymous connection. + + RROOOOTTUUSSEE__SSAASSLL on/true/yes/off/false/no + Enable RROOOOTTUUSSEE__SSAASSLL to enable SASL authentication when connecting + to an LDAP server from a privileged process, such as ssuuddoo. + + RROOOOTTSSAASSLL__AAUUTTHH__IIDD identity + The SASL user name to use when RROOOOTTUUSSEE__SSAASSLL is enabled. + + SSAASSLL__SSEECCPPRROOPPSS none/properties + SASL security properties or _n_o_n_e for no properties. See the SASL + programmer's manual for details. + + KKRRBB55__CCCCNNAAMMEE file name + The path to the Kerberos 5 credential cache to use when + authenticating with the remote server. + + + +1.7.0 October 24, 2008 7 + + + + + +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) + + + See the ldap.conf entry in the EXAMPLES section. + + 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. + 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 + ones. + + The following sources are recognized: + + files read sudoers from F + ldap read sudoers from LDAP + + In addition, the entry [NOTFOUND=return] will short-circuit the search + if the user was not found in the preceding source. + + 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 + + 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: + + sudoers: files + + Note that _@_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. + +FFIILLEESS + _@_l_d_a_p___c_o_n_f_@ LDAP configuration file + + _@_n_s_s_w_i_t_c_h___c_o_n_f_@ determines sudoers source order + +EEXXAAMMPPLLEESS + EExxaammppllee llddaapp..ccoonnff + + # Either specify one or more URIs or one or more host:port pairs. + # If neither is specified sudo will default to localhost, port 389. + # + #host ldapserver + #host ldapserver1 ldapserver2:390 + # + # Default port if host is specified without one, defaults to 389. + #port 389 + # + # URI will override the host and port settings. + + + +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 + # + # The amount of time, in seconds, to wait while trying to connect to + # an LDAP server. + bind_timelimit 30 + # + # The amount of time, in seconds, to wait while performing an LDAP query. + timelimit 30 + # + # must be set or sudo will ignore LDAP + sudoers_base ou=SUDOers,dc=example,dc=com + # + # verbose sudoers matching from ldap + #sudoers_debug 2 + # + # optional proxy credentials + #binddn + #bindpw + #rootbinddn + # + # LDAP protocol version, defaults to 3 + #ldap_version 3 + # + # Define if you want to use an encrypted LDAP connection. + # Typically, you must also set the port to 636 (ldaps). + #ssl on + # + # Define if you want to use port 389 and switch to + # encryption before the bind credentials are sent. + # Only supported by LDAP servers that support the start_tls + # extension such as OpenLDAP. + #ssl start_tls + # + # Additional TLS options follow that allow tweaking of the + # SSL/TLS connection. + # + #tls_checkpeer yes # verify server SSL certificate + #tls_checkpeer no # ignore server SSL certificate + # + # If you enable tls_checkpeer, specify either tls_cacertfile + # or tls_cacertdir. Only supported when using OpenLDAP. + # + #tls_cacertfile /etc/certs/trusted_signers.pem + #tls_cacertdir /etc/certs + # + # For systems that don't have /dev/random + # use this along with PRNGD or EGD.pl to seed the + # random number pool to generate cryptographic session keys. + # Only supported when using OpenLDAP. + # + #tls_randfile /etc/egd-pool + # + + + +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. + # + #tls_ciphers + # + # Sudo can provide a client certificate when communicating to + # the LDAP server. + # Tips: + # * Enable both lines at the same time. + # * Do not password protect the key file. + # * Ensure the keyfile is only readable by root. + # + # For OpenLDAP: + #tls_cert /etc/certs/client_cert.pem + #tls_key /etc/certs/client_key.pem + # + # For 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 + # + # If using SASL authentication for LDAP (OpenSSL) + # use_sasl yes + # sasl_auth_id + # rootuse_sasl yes + # rootsasl_auth_id + # sasl_secprops none + # krb5_ccname /etc/.ldapcache + + SSuuddoo sscchheemmaa ffoorr OOppeennLLDDAAPP + + The following schema is in OpenLDAP format. Simply copy it to the + schema directory (e.g. _/_e_t_c_/_o_p_e_n_l_d_a_p_/_s_c_h_e_m_a), add the proper include + line in slapd.conf and restart ssllaappdd. + + attributetype ( 1.3.6.1.4.1.15953.9.1.1 + NAME 'sudoUser' + DESC 'User(s) who may run sudo' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.2 + NAME 'sudoHost' + DESC 'Host(s) who may run sudo' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.3 + NAME 'sudoCommand' + + + +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 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.4 + NAME 'sudoRunAs' + DESC 'User(s) impersonated by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.5 + NAME 'sudoOption' + DESC 'Options(s) followed by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.6 + NAME 'sudoRunAsUser' + DESC 'User(s) impersonated by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.7 + NAME 'sudoRunAsGroup' + DESC 'Group(s) impersonated by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL + DESC 'Sudoer Entries' + MUST ( cn ) + MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ + sudoRunAsGroup $ sudoOption $ 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) + +CCAAVVEEAATTSS + The way that _s_u_d_o_e_r_s is parsed differs between Note that there are + differences in the way that LDAP-based _s_u_d_o_e_r_s is parsed compared to + file-based _s_u_d_o_e_r_s. See the "Differences between LDAP and non-LDAP + sudoers" section for more information. + +BBUUGGSS + If you feel you have found a bug in ssuuddoo, please submit a bug report at + http://www.sudo.ws/sudo/bugs/ + +SSUUPPPPOORRTT + Limited free support is available via the sudo-users mailing list, see + 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 + merchantability and fitness for a particular purpose are disclaimed. + See the LICENSE file distributed with ssuuddoo or + http://www.sudo.ws/sudo/license.html for complete details. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1.7.0 October 24, 2008 12 + + diff --git a/sudoers.ldap.man.in b/sudoers.ldap.man.in new file mode 100644 index 0000000..998786c --- /dev/null +++ b/sudoers.ldap.man.in @@ -0,0 +1,778 @@ +.\" Copyright (c) 2003-2008 +.\" 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. +.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Sudo: sudoers.ldap.man.in,v 1.11 2008/10/24 13:52:19 millert Exp $ +.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.05) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` +. ds C' +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "SUDOERS.LDAP @mansectform@" +.TH SUDOERS.LDAP @mansectform@ "October 24, 2008" "1.7.0" "MAINTENANCE COMMANDS" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +sudoers.ldap \- sudo LDAP configuration +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +In addition to the standard \fIsudoers\fR file, \fBsudo\fR may be configured +via \s-1LAP\s0. This can be especially useful for synchronizing \fIsudoers\fR +in a large, distributed environment. +.PP +Using \s-1LDAP\s0 for \fIsudoers\fR has several benefits: +.IP "\(bu" 4 +\&\fBsudo\fR no longer needs to read \fIsudoers\fR in its entirety. When +\&\s-1LDAP\s0 is used, there are only two or three \s-1LDAP\s0 queries per invocation. +This makes it especially fast and particularly usable in \s-1LDAP\s0 +environments. +.IP "\(bu" 4 +\&\fBsudo\fR no longer exits if there is a typo in \fIsudoers\fR. +It is not possible to load \s-1LDAP\s0 data into the server that does +not conform to the sudoers schema, so proper syntax is guaranteed. +It is still possible to have typos in a user or host name, but +this will not prevent \fBsudo\fR from running. +.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 +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. +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. +.PP +Another major difference between \s-1LDAP\s0 and file-based \fIsudoers\fR +is that in \s-1LDAP\s0, \fBsudo\fR\-specific Aliases are not supported. +.PP +For the most part, there is really no need for \fBsudo\fR\-specific +Aliases. Unix groups or user netgroups can be used in place of +User_Aliases and RunasAliases. Host netgroups can be used in place +of HostAliases. Since Unix groups and netgroups can also be stored +in \s-1LDAP\s0 there is no real need for \fBsudo\fR\-specific aliases. +.PP +Cmnd_Aliases are not really required either since it is possible +to have multiple users listed in a sudoRole. Instead of defining +a Cmnd_Alias that is referenced by multiple users, one can create +a sudoRole that contains the commands and assign multiple users +to it. +.Sh "SUDOers \s-1LDAP\s0 container" +.IX Subsection "SUDOers LDAP container" +The \fIsudoers\fR configuration is contained in the \f(CW\*(C`ou=SUDOers\*(C'\fR \s-1LDAP\s0 +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 +the following example, the \f(CW\*(C`SSH_AUTH_SOCK\*(C'\fR variable will be preserved +in the environment for all users. +.PP +.Vb 6 +\& dn: cn=defaults,ou=SUDOers,dc=example,dc=com +\& objectClass: top +\& objectClass: sudoRole +\& cn: defaults +\& description: Default sudoOption\*(Aqs go here +\& sudoOption: env_keep+=SSH_AUTH_SOCK +.Ve +.PP +The equivalent of a sudoer in \s-1LDAP\s0 is a \f(CW\*(C`sudoRole\*(C'\fR. It consists of +the following components: +.IP "\fBsudoUser\fR" 4 +.IX Item "sudoUser" +A user name, uid (prefixed with \f(CW\*(Aq#\*(Aq\fR), Unix group (prefixed with +a \f(CW\*(Aq%\*(Aq\fR) or user netgroup (prefixed with a \f(CW\*(Aq+\*(Aq\fR). +.IP "\fBsudoHost\fR" 4 +.IX Item "sudoHost" +A host name, \s-1IP\s0 address, \s-1IP\s0 network, or host netgroup (prefixed +with a \f(CW\*(Aq+\*(Aq\fR). +The special value \f(CW\*(C`ALL\*(C'\fR will match any host. +.IP "\fBsudoCommand\fR" 4 +.IX Item "sudoCommand" +A Unix command with optional command line arguments, potentially +including globbing characters (aka wild cards). +The special value \f(CW\*(C`ALL\*(C'\fR will match any command. +If a command is prefixed with an exclamation point \f(CW\*(Aq!\*(Aq\fR, the +user will be prohibited from running that command. +.IP "\fBsudoOption\fR" 4 +.IX Item "sudoOption" +Identical in function to the global options described above, but +specific to the \f(CW\*(C`sudoRole\*(C'\fR in which it resides. +.IP "\fBsudoRunAsUser\fR" 4 +.IX Item "sudoRunAsUser" +A user name or uid (prefixed with \f(CW\*(Aq#\*(Aq\fR) that commands may be run +as or a Unix group (prefixed with a \f(CW\*(Aq%\*(Aq\fR) or user netgroup (prefixed +with a \f(CW\*(Aq+\*(Aq\fR) that contains a list of users that commands may be +run as. +The special value \f(CW\*(C`ALL\*(C'\fR will match any user. +.IP "\fBsudoRunAsGroup\fR" 4 +.IX Item "sudoRunAsGroup" +A Unix group or gid (prefixed with \f(CW\*(Aq#\*(Aq\fR) that commands may be run as. +The special value \f(CW\*(C`ALL\*(C'\fR will match any group. +.PP +Each component listed above should contain a single value, but there +may be multiple instances of each component type. A sudoRole must +contain at least one \f(CW\*(C`sudoUser\*(C'\fR, \f(CW\*(C`sudoHost\*(C'\fR and \f(CW\*(C`sudoCommand\*(C'\fR. +.PP +The following example allows users in group wheel to run any command +on any host via \fBsudo\fR: +.PP +.Vb 7 +\& dn: cn=%wheel,ou=SUDOers,dc=example,dc=com +\& objectClass: top +\& objectClass: sudoRole +\& cn: %wheel +\& sudoUser: %wheel +\& sudoHost: ALL +\& sudoCommand: ALL +.Ve +.Sh "Anatomy of \s-1LDAP\s0 sudoers lookup" +.IX Subsection "Anatomy of LDAP sudoers lookup" +When looking up a sudoer using \s-1LDAP\s0 there are only two or three +\&\s-1LDAP\s0 queries per invocation. The first query is to parse the global +options. The second is to match against the user's name and the +groups that the user belongs to. (The special \s-1ALL\s0 tag is matched +in this query too.) If no match is returned for the user's name +and groups, a third query returns all entries containing user +netgroups and checks to see if the user belongs to any of them. +.Sh "Differences between \s-1LDAP\s0 and non-LDAP sudoers" +.IX Subsection "Differences between LDAP and non-LDAP sudoers" +There are some subtle differences in the way sudoers is handled +once in \s-1LDAP\s0. Probably the biggest is that according to the \s-1RFC\s0, +\&\s-1LDAP\s0 ordering is arbitrary and you cannot expect that Attributes +and Entries are returned in any specific order. If there are +conflicting command rules on an entry, the negative takes precedence. +This is called paranoid behavior (not necessarily the most specific +match). +.PP +Here is an example: +.PP +.Vb 5 +\& # /etc/sudoers: +\& # Allow all commands except shell +\& johnny ALL=(root) ALL,!/bin/sh +\& # Always allows all commands because ALL is matched last +\& puddles ALL=(root) !/bin/sh,ALL +\& +\& # LDAP equivalent of johnny +\& # Allows all commands except shell +\& dn: cn=role1,ou=Sudoers,dc=my\-domain,dc=com +\& objectClass: sudoRole +\& objectClass: top +\& cn: role1 +\& sudoUser: johnny +\& sudoHost: ALL +\& sudoCommand: ALL +\& sudoCommand: !/bin/sh +\& +\& # LDAP equivalent of puddles +\& # Notice that even though ALL comes last, it still behaves like +\& # role1 since the LDAP code assumes the more paranoid configuration +\& dn: cn=role2,ou=Sudoers,dc=my\-domain,dc=com +\& objectClass: sudoRole +\& objectClass: top +\& cn: role2 +\& sudoUser: puddles +\& sudoHost: ALL +\& sudoCommand: !/bin/sh +\& sudoCommand: ALL +.Ve +.PP +Another difference is that negations on the Host, User or Runas are +currently ignorred. For example, the following attributes do not +behave the way one might expect. +.PP +.Vb 3 +\& # does not match all but joe +\& # rather, does not match anyone +\& sudoUser: !joe +\& +\& # does not match all but joe +\& # rather, matches everyone including Joe +\& sudoUser: ALL +\& sudoUser: !joe +\& +\& # does not match all but web01 +\& # rather, matches all hosts including web01 +\& sudoHost: ALL +\& sudoHost: !web01 +.Ve +.Sh "Sudoers Schema" +.IX Subsection "Sudoers Schema" +In order to use \fBsudo\fR's \s-1LDAP\s0 support, the \fBsudo\fR schema must be +installed on your \s-1LDAP\s0 server. In addition, be sure to index the +\&'sudoUser' attribute. +.PP +Three versions of the schema: one for OpenLDAP servers (\fIschema.OpenLDAP\fR), +one for Netscape-derived servers (\fIschema.iPlanet\fR), and one for +Microsoft Active Directory (\fIschema.ActiveDirectory\fR) may +be found in the \fBsudo\fR distribution. +.PP +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. +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 +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 +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 +.IX Item "URI ldap[s]://[hostname[:port]] ..." +Specifies a whitespace-delimited list of one or more URIs describing +the \s-1LDAP\s0 server(s) to connect to. The \fIprotocol\fR may be either \fBldap\fR +or \fBldaps\fR, the latter being for servers that support \s-1TLS\s0 (\s-1SSL\s0) +encryption. If no \fIport\fR is specified, the default is port 389 for +\&\f(CW\*(C`ldap://\*(C'\fR or port 636 for \f(CW\*(C`ldaps://\*(C'\fR. If no \fIhostname\fR is specified, +\&\fBsudo\fR will connect to \fBlocalhost\fR. Only systems using the OpenSSL +libraries support the mixing of \f(CW\*(C`ldap://\*(C'\fR and \f(CW\*(C`ldaps://\*(C'\fR URIs. +The Netscape-derived libraries used on most commercial versions of +Unix are only capable of supporting one or the other. +.IP "\fB\s-1HOST\s0\fR name[:port] ..." 4 +.IX Item "HOST name[:port] ..." +If no \fB\s-1URI\s0\fR is specified, the \fB\s-1HOST\s0\fR parameter specifies a +whitespace-delimited list of \s-1LDAP\s0 servers to connect to. Each host +may include an optional \fIport\fR separated by a colon (':'). The +\&\fB\s-1HOST\s0\fR parameter is deprecated in favor of the \fB\s-1URI\s0\fR specification +and is included for backwards compatibility. +.IP "\fB\s-1PORT\s0\fR port_number" 4 +.IX Item "PORT port_number" +If no \fB\s-1URI\s0\fR is specified, the \fB\s-1PORT\s0\fR parameter specifies the +default port to connect to on the \s-1LDAP\s0 server if a \fB\s-1HOST\s0\fR parameter +does not specify the port itself. If no \fB\s-1PORT\s0\fR parameter is used, +the default is port 389 for \s-1LDAP\s0 and port 636 for \s-1LDAP\s0 over \s-1TLS\s0 +(\s-1SSL\s0). The \fB\s-1PORT\s0\fR parameter is deprecated in favor of the \fB\s-1URI\s0\fR +specification and is included for backwards compatibility. +.IP "\fB\s-1BIND_TIMELIMIT\s0\fR seconds" 4 +.IX Item "BIND_TIMELIMIT seconds" +The \fB\s-1BIND_TIMELIMIT\s0\fR parameter specifies the amount of time, in seconds, +to wait while trying to connect to an \s-1LDAP\s0 server. If multiple \fB\s-1URI\s0\fRs or +\&\fB\s-1HOST\s0\fRs are specified, this is the amount of time to wait before trying +the next one in the list. +.IP "\fB\s-1TIMELIMIT\s0\fR seconds" 4 +.IX Item "TIMELIMIT seconds" +The \fB\s-1TIMELIMIT\s0\fR parameter specifies the amount of time, in seconds, +to wait for a response to an \s-1LDAP\s0 query. +.IP "\fB\s-1SUDOERS_BASE\s0\fR base" 4 +.IX Item "SUDOERS_BASE base" +The base \s-1DN\s0 to use when performing \fBsudo\fR \s-1LDAP\s0 queries. Typically +this is of the form \f(CW\*(C`ou=SUDOers,dc=example,dc=com\*(C'\fR for the domain +\&\f(CW\*(C`example.com\*(C'\fR. +.IP "\fB\s-1SUDOERS_DEBUG\s0\fR debug_level" 4 +.IX Item "SUDOERS_DEBUG debug_level" +This sets the debug level for \fBsudo\fR \s-1LDAP\s0 queries. Debugging +information is printed to the standard error. A value of 1 results +in a moderate amount of debugging information. A value of 2 shows +the results of the matches themselves. This parameter should not +be set in a production environment as the extra information is +likely to confuse users. +.IP "\fB\s-1BINDDN\s0\fR \s-1DN\s0" 4 +.IX Item "BINDDN DN" +The \fB\s-1BINDDN\s0\fR parameter specifies the identity, in the form of a +Distinguished Name (\s-1DN\s0), to use when performing \s-1LDAP\s0 operations. +If not specified, \s-1LDAP\s0 operations are performed with an anonymous +identity. By default, most \s-1LDAP\s0 servers will allow anonymous access. +.IP "\fB\s-1BINDPW\s0\fR secret" 4 +.IX Item "BINDPW secret" +The \fB\s-1BINDPW\s0\fR parameter specifies the password to use when performing +\&\s-1LDAP\s0 operations. This is typically used in conjunction with the +\&\fB\s-1BINDDN\s0\fR parameter. +.IP "\fB\s-1ROOTBINDDN\s0\fR \s-1DN\s0" 4 +.IX Item "ROOTBINDDN DN" +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. +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" +The version of the \s-1LDAP\s0 protocol to use when connecting to the server. +The default value is protocol version 3. +.IP "\fB\s-1SSL\s0\fR on/true/yes/off/false/no" 4 +.IX Item "SSL on/true/yes/off/false/no" +If the \fB\s-1SSL\s0\fR parameter is set to \f(CW\*(C`on\*(C'\fR, \f(CW\*(C`true\*(C'\fR or \f(CW\*(C`yes\*(C'\fR, \s-1TLS\s0 +(\s-1SSL\s0) encryption is always used when communicating with the \s-1LDAP\s0 +server. Typically, this involves connecting to the server on port +636 (ldaps). +.IP "\fB\s-1SSL\s0\fR start_tls" 4 +.IX Item "SSL start_tls" +If the \fB\s-1SSL\s0\fR parameter is set to \f(CW\*(C`start_tls\*(C'\fR, the \s-1LDAP\s0 server +connection is initiated normally and \s-1TLS\s0 encryption is begun before +the bind credentials are sent. This has the advantage of not +requiring a dedicated port for encrypted communications. This +parameter is only supported by \s-1LDAP\s0 servers that honor the \f(CW\*(C`start_tls\*(C'\fR +extension, such as the OpenLDAP server. +.IP "\fB\s-1TLS_CHECKPEER\s0\fR on/true/yes/off/false/no" 4 +.IX Item "TLS_CHECKPEER on/true/yes/off/false/no" +If enabled, \fB\s-1TLS_CHECKPEER\s0\fR will cause the \s-1LDAP\s0 server's \s-1TLS\s0 +certificated to be verified. If the server's \s-1TLS\s0 certificate cannot +be verified (usually because it is signed by an unknown certificate +authority), \fBsudo\fR will be unable to connect to it. If \fB\s-1TLS_CHECKPEER\s0\fR +is disabled, no check is made. +.IP "\fB\s-1TLS_CACERTFILE\s0\fR file name" 4 +.IX Item "TLS_CACERTFILE file name" +The path to a certificate authority bundle which contains the certificates +for all the Certificate Authorities the client knows to be valid, +e.g. \fI/etc/ssl/ca\-bundle.pem\fR. +This option is only supported by the OpenLDAP libraries. +.IP "\fB\s-1TLS_CACERTDIR\s0\fR directory" 4 +.IX Item "TLS_CACERTDIR directory" +Similar to \fB\s-1TLS_CACERTFILE\s0\fR but instead of a file, it is a +directory containing individual Certificate Authority certificates, +e.g. \fI/etc/ssl/certs\fR. +The directory specified by \fB\s-1TLS_CACERTDIR\s0\fR is checked after +\&\fB\s-1TLS_CACERTFILE\s0\fR. +This option is only supported by the OpenLDAP libraries. +.IP "\fB\s-1TLS_CERT\s0\fR file name" 4 +.IX Item "TLS_CERT file name" +The path to a file containing the client certificate which can +be used to authenticate the client to the \s-1LDAP\s0 server. +The certificate type depends on the \s-1LDAP\s0 libraries used. +.Sp +OpenLDAP: + \f(CW\*(C`tls_cert /etc/ssl/client_cert.pem\*(C'\fR +.Sp +Netscape-derived: + \f(CW\*(C`tls_cert /var/ldap/cert7.db\*(C'\fR +.Sp +When using Netscape-derived libraries, this file may also contain +Certificate Authority certificates. +.IP "\fB\s-1TLS_KEY\s0\fR file name" 4 +.IX Item "TLS_KEY file name" +The path to a file containing the private key which matches the +certificate specified by \fB\s-1TLS_CERT\s0\fR. The private key must not be +password-protected. The key type depends on the \s-1LDAP\s0 libraries +used. +.Sp +OpenLDAP: + \f(CW\*(C`tls_key /etc/ssl/client_key.pem\*(C'\fR +.Sp +Netscape-derived: + \f(CW\*(C`tls_key /var/ldap/key3.db\*(C'\fR +.IP "\fB\s-1TLS_RANDFILE\s0\fR file name" 4 +.IX Item "TLS_RANDFILE file name" +The \fB\s-1TLS_RANDFILE\s0\fR parameter specifies the path to an entropy +source for systems that lack a random device. It is generally used +in conjunction with \fIprngd\fR or \fIegd\fR. +This option is only supported by the OpenLDAP libraries. +.IP "\fB\s-1TLS_CIPHERS\s0\fR cipher list" 4 +.IX Item "TLS_CIPHERS cipher list" +The \fB\s-1TLS_CIPHERS\s0\fR parameter allows the administer to restrict +which encryption algorithms may be used for \s-1TLS\s0 (\s-1SSL\s0) connections. +See the OpenSSL manual for a list of valid ciphers. +This option is only supported by the OpenLDAP libraries. +.IP "\fB\s-1USE_SASL\s0\fR on/true/yes/off/false/no" 4 +.IX Item "USE_SASL on/true/yes/off/false/no" +Enable \fB\s-1USE_SASL\s0\fR for \s-1LDAP\s0 servers that support \s-1SASL\s0 authentication. +.IP "\fB\s-1SASL_AUTH_ID\s0\fR identity" 4 +.IX Item "SASL_AUTH_ID identity" +The \s-1SASL\s0 user name to use when connecting to the \s-1LDAP\s0 server. +By default, \fBsudo\fR will use an anonymous connection. +.IP "\fB\s-1ROOTUSE_SASL\s0\fR on/true/yes/off/false/no" 4 +.IX Item "ROOTUSE_SASL on/true/yes/off/false/no" +Enable \fB\s-1ROOTUSE_SASL\s0\fR to enable \s-1SASL\s0 authentication when connecting +to an \s-1LDAP\s0 server from a privileged process, such as \fBsudo\fR. +.IP "\fB\s-1ROOTSASL_AUTH_ID\s0\fR identity" 4 +.IX Item "ROOTSASL_AUTH_ID identity" +The \s-1SASL\s0 user name to use when \fB\s-1ROOTUSE_SASL\s0\fR is enabled. +.IP "\fB\s-1SASL_SECPROPS\s0\fR none/properties" 4 +.IX Item "SASL_SECPROPS none/properties" +\&\s-1SASL\s0 security properties or \fInone\fR for no properties. See the +\&\s-1SASL\s0 programmer's manual for details. +.IP "\fB\s-1KRB5_CCNAME\s0\fR file name" 4 +.IX Item "KRB5_CCNAME file name" +The path to the Kerberos 5 credential cache to use when authenticating +with the remote server. +.PP +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 +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. +.PP +The following sources are recognized: +.PP +.Vb 2 +\& files read sudoers from F<@sysconfdir@/sudoers> +\& ldap read sudoers from LDAP +.Ve +.PP +In addition, the entry \f(CW\*(C`[NOTFOUND=return]\*(C'\fR will short-circuit the +search if the user was not found in the preceding source. +.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 +If the \fI\f(CI@nsswitch_conf\fI@\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 +operating system does not use an nsswitch.conf file. +.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 +.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 +.IX Item "@nsswitch_conf@" +determines sudoers source order +.SH "EXAMPLES" +.IX Header "EXAMPLES" +.Sh "Example ldap.conf" +.IX Subsection "Example ldap.conf" +.Vb 10 +\& # Either specify one or more URIs or one or more host:port pairs. +\& # If neither is specified sudo will default to localhost, port 389. +\& # +\& #host ldapserver +\& #host ldapserver1 ldapserver2:390 +\& # +\& # Default port if host is specified without one, defaults to 389. +\& #port 389 +\& # +\& # URI will override the host and port settings. +\& uri ldap://ldapserver +\& #uri ldaps://secureldapserver +\& #uri ldaps://secureldapserver ldap://ldapserver +\& # +\& # The amount of time, in seconds, to wait while trying to connect to +\& # an LDAP server. +\& bind_timelimit 30 +\& # +\& # The amount of time, in seconds, to wait while performing an LDAP query. +\& timelimit 30 +\& # +\& # must be set or sudo will ignore LDAP +\& sudoers_base ou=SUDOers,dc=example,dc=com +\& # +\& # verbose sudoers matching from ldap +\& #sudoers_debug 2 +\& # +\& # optional proxy credentials +\& #binddn +\& #bindpw +\& #rootbinddn +\& # +\& # LDAP protocol version, defaults to 3 +\& #ldap_version 3 +\& # +\& # Define if you want to use an encrypted LDAP connection. +\& # Typically, you must also set the port to 636 (ldaps). +\& #ssl on +\& # +\& # Define if you want to use port 389 and switch to +\& # encryption before the bind credentials are sent. +\& # Only supported by LDAP servers that support the start_tls +\& # extension such as OpenLDAP. +\& #ssl start_tls +\& # +\& # Additional TLS options follow that allow tweaking of the +\& # SSL/TLS connection. +\& # +\& #tls_checkpeer yes # verify server SSL certificate +\& #tls_checkpeer no # ignore server SSL certificate +\& # +\& # If you enable tls_checkpeer, specify either tls_cacertfile +\& # or tls_cacertdir. Only supported when using OpenLDAP. +\& # +\& #tls_cacertfile /etc/certs/trusted_signers.pem +\& #tls_cacertdir /etc/certs +\& # +\& # For systems that don\*(Aqt have /dev/random +\& # use this along with PRNGD or EGD.pl to seed the +\& # random number pool to generate cryptographic session keys. +\& # Only supported when using OpenLDAP. +\& # +\& #tls_randfile /etc/egd\-pool +\& # +\& # You may restrict which ciphers are used. Consult your SSL +\& # documentation for which options go here. +\& # Only supported when using OpenLDAP. +\& # +\& #tls_ciphers +\& # +\& # Sudo can provide a client certificate when communicating to +\& # the LDAP server. +\& # Tips: +\& # * Enable both lines at the same time. +\& # * Do not password protect the key file. +\& # * Ensure the keyfile is only readable by root. +\& # +\& # For OpenLDAP: +\& #tls_cert /etc/certs/client_cert.pem +\& #tls_key /etc/certs/client_key.pem +\& # +\& # For 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 +\& # +\& # If using SASL authentication for LDAP (OpenSSL) +\& # use_sasl yes +\& # sasl_auth_id +\& # rootuse_sasl yes +\& # rootsasl_auth_id +\& # sasl_secprops none +\& # krb5_ccname /etc/.ldapcache +.Ve +.Sh "Sudo schema for OpenLDAP" +.IX Subsection "Sudo schema for OpenLDAP" +The following schema is in OpenLDAP format. Simply copy it to the +schema directory (e.g. \fI/etc/openldap/schema\fR), add the proper +\&\f(CW\*(C`include\*(C'\fR line in \f(CW\*(C`slapd.conf\*(C'\fR and restart \fBslapd\fR. +.PP +.Vb 6 +\& attributetype ( 1.3.6.1.4.1.15953.9.1.1 +\& NAME \*(AqsudoUser\*(Aq +\& DESC \*(AqUser(s) who may run sudo\*(Aq +\& EQUALITY caseExactIA5Match +\& SUBSTR caseExactIA5SubstringsMatch +\& SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +\& +\& attributetype ( 1.3.6.1.4.1.15953.9.1.2 +\& NAME \*(AqsudoHost\*(Aq +\& DESC \*(AqHost(s) who may run sudo\*(Aq +\& EQUALITY caseExactIA5Match +\& SUBSTR caseExactIA5SubstringsMatch +\& SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +\& +\& attributetype ( 1.3.6.1.4.1.15953.9.1.3 +\& NAME \*(AqsudoCommand\*(Aq +\& DESC \*(AqCommand(s) to be executed by sudo\*(Aq +\& EQUALITY caseExactIA5Match +\& SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +\& +\& attributetype ( 1.3.6.1.4.1.15953.9.1.4 +\& NAME \*(AqsudoRunAs\*(Aq +\& DESC \*(AqUser(s) impersonated by sudo\*(Aq +\& EQUALITY caseExactIA5Match +\& SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +\& +\& attributetype ( 1.3.6.1.4.1.15953.9.1.5 +\& NAME \*(AqsudoOption\*(Aq +\& DESC \*(AqOptions(s) followed by sudo\*(Aq +\& EQUALITY caseExactIA5Match +\& SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +\& +\& attributetype ( 1.3.6.1.4.1.15953.9.1.6 +\& NAME \*(AqsudoRunAsUser\*(Aq +\& DESC \*(AqUser(s) impersonated by sudo\*(Aq +\& EQUALITY caseExactIA5Match +\& SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +\& +\& attributetype ( 1.3.6.1.4.1.15953.9.1.7 +\& NAME \*(AqsudoRunAsGroup\*(Aq +\& DESC \*(AqGroup(s) impersonated by sudo\*(Aq +\& EQUALITY caseExactIA5Match +\& SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +\& +\& objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME \*(AqsudoRole\*(Aq SUP top STRUCTURAL +\& DESC \*(AqSudoer Entries\*(Aq +\& MUST ( cn ) +\& MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ +\& 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) +.SH "CAVEATS" +.IX Header "CAVEATS" +The way that \fIsudoers\fR is parsed differs between Note that there +are differences in the way that LDAP-based \fIsudoers\fR is parsed +compared to file-based \fIsudoers\fR. See the \*(L"Differences between +\&\s-1LDAP\s0 and non-LDAP sudoers\*(R" section for more information. +.SH "BUGS" +.IX Header "BUGS" +If you feel you have found a bug in \fBsudo\fR, please submit a bug report +at http://www.sudo.ws/sudo/bugs/ +.SH "SUPPORT" +.IX Header "SUPPORT" +Limited free support is available via the sudo-users mailing list, +see http://www.sudo.ws/mailman/listinfo/sudo\-users to subscribe or +search the archives. +.SH "DISCLAIMER" +.IX Header "DISCLAIMER" +\&\fBsudo\fR is provided ``\s-1AS\s0 \s-1IS\s0'' and any express or implied warranties, +including, but not limited to, the implied warranties of merchantability +and fitness for a particular purpose are disclaimed. See the \s-1LICENSE\s0 +file distributed with \fBsudo\fR or http://www.sudo.ws/sudo/license.html +for complete details. diff --git a/sudoers.ldap.pod b/sudoers.ldap.pod new file mode 100644 index 0000000..3b36ddd --- /dev/null +++ b/sudoers.ldap.pod @@ -0,0 +1,694 @@ +Copyright (c) 2003-2008 + 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. +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +$Sudo: sudoers.ldap.pod,v 1.10 2008/05/10 13:18:47 millert Exp $ +=pod + +=head1 NAME + +sudoers.ldap - sudo LDAP configuration + +=head1 DESCRIPTION + +In addition to the standard I file, B may be configured +via LAP. This can be especially useful for synchronizing I +in a large, distributed environment. + +Using LDAP for I has several benefits: + +=over 4 + +=item * + +B no longer needs to read I in its entirety. When +LDAP is used, there are only two or three LDAP queries per invocation. +This makes it especially fast and particularly usable in LDAP +environments. + +=item * + +B no longer exits if there is a typo in I. +It is not possible to load LDAP data into the server that does +not conform to the sudoers schema, so proper syntax is guaranteed. +It is still possible to have typos in a user or host name, but +this will not prevent B from running. + +=item * + +It is possible to specify per-entry options that override the global +default options. F<@sysconfdir@/sudoers> only supports default options and +limited options associated with user/host/commands/aliases. The +syntax is complicated and can be difficult for users to understand. +Placing the options directly in the entry is more natural. + +=item * + +The B program is no longer needed. B provides +locking and syntax checking of the F<@sysconfdir@/sudoers> file. +Since LDAP updates are atomic, locking is no longer necessary. +Because syntax is checked when the data is inserted into LDAP, there +is no need for a specialized tool to check syntax. + +=back + +Another major difference between LDAP and file-based I +is that in LDAP, B-specific Aliases are not supported. + +For the most part, there is really no need for B-specific +Aliases. Unix groups or user netgroups can be used in place of +User_Aliases and RunasAliases. Host netgroups can be used in place +of HostAliases. Since Unix groups and netgroups can also be stored +in LDAP there is no real need for B-specific aliases. + +Cmnd_Aliases are not really required either since it is possible +to have multiple users listed in a sudoRole. Instead of defining +a Cmnd_Alias that is referenced by multiple users, one can create +a sudoRole that contains the commands and assign multiple users +to it. + +=head2 SUDOers LDAP container + +The I configuration is contained in the C LDAP +container. + +Sudo first looks for the C entry in the SUDOers container. +If found, the multi-valued C attribute is parsed in the +same manner as a global C line in F<@sysconfdir@/sudoers>. In +the following example, the C variable will be preserved +in the environment for all users. + + dn: cn=defaults,ou=SUDOers,dc=example,dc=com + objectClass: top + objectClass: sudoRole + cn: defaults + description: Default sudoOption's go here + sudoOption: env_keep+=SSH_AUTH_SOCK + +The equivalent of a sudoer in LDAP is a C. It consists of +the following components: + +=over 4 + +=item B + +A user name, uid (prefixed with C<'#'>), Unix group (prefixed with +a C<'%'>) or user netgroup (prefixed with a C<'+'>). + +=item B + +A host name, IP address, IP network, or host netgroup (prefixed +with a C<'+'>). +The special value C will match any host. + +=item B + +A Unix command with optional command line arguments, potentially +including globbing characters (aka wild cards). +The special value C will match any command. +If a command is prefixed with an exclamation point C<'!'>, the +user will be prohibited from running that command. + +=item B + +Identical in function to the global options described above, but +specific to the C in which it resides. + +=item B + +A user name or uid (prefixed with C<'#'>) that commands may be run +as or a Unix group (prefixed with a C<'%'>) or user netgroup (prefixed +with a C<'+'>) that contains a list of users that commands may be +run as. +The special value C will match any user. + +=item B + +A Unix group or gid (prefixed with C<'#'>) that commands may be run as. +The special value C will match any group. + +=back + +Each component listed above should contain a single value, but there +may be multiple instances of each component type. A sudoRole must +contain at least one C, C and C. + +The following example allows users in group wheel to run any command +on any host via B: + + dn: cn=%wheel,ou=SUDOers,dc=example,dc=com + objectClass: top + objectClass: sudoRole + cn: %wheel + sudoUser: %wheel + sudoHost: ALL + sudoCommand: ALL + +=head2 Anatomy of LDAP sudoers lookup + +When looking up a sudoer using LDAP there are only two or three +LDAP queries per invocation. The first query is to parse the global +options. The second is to match against the user's name and the +groups that the user belongs to. (The special ALL tag is matched +in this query too.) If no match is returned for the user's name +and groups, a third query returns all entries containing user +netgroups and checks to see if the user belongs to any of them. + +=head2 Differences between LDAP and non-LDAP sudoers + +There are some subtle differences in the way sudoers is handled +once in LDAP. Probably the biggest is that according to the RFC, +LDAP ordering is arbitrary and you cannot expect that Attributes +and Entries are returned in any specific order. If there are +conflicting command rules on an entry, the negative takes precedence. +This is called paranoid behavior (not necessarily the most specific +match). + +Here is an example: + + # /etc/sudoers: + # Allow all commands except shell + johnny ALL=(root) ALL,!/bin/sh + # Always allows all commands because ALL is matched last + puddles ALL=(root) !/bin/sh,ALL + + # LDAP equivalent of johnny + # Allows all commands except shell + dn: cn=role1,ou=Sudoers,dc=my-domain,dc=com + objectClass: sudoRole + objectClass: top + cn: role1 + sudoUser: johnny + sudoHost: ALL + sudoCommand: ALL + sudoCommand: !/bin/sh + + # LDAP equivalent of puddles + # Notice that even though ALL comes last, it still behaves like + # role1 since the LDAP code assumes the more paranoid configuration + dn: cn=role2,ou=Sudoers,dc=my-domain,dc=com + objectClass: sudoRole + objectClass: top + cn: role2 + sudoUser: puddles + sudoHost: ALL + sudoCommand: !/bin/sh + sudoCommand: ALL + +Another difference is that negations on the Host, User or Runas are +currently ignorred. For example, the following attributes do not +behave the way one might expect. + + # does not match all but joe + # rather, does not match anyone + sudoUser: !joe + + # does not match all but joe + # rather, matches everyone including Joe + sudoUser: ALL + sudoUser: !joe + + # does not match all but web01 + # rather, matches all hosts including web01 + sudoHost: ALL + sudoHost: !web01 + +=head2 Sudoers Schema + +In order to use B's LDAP support, the B schema must be +installed on your LDAP server. In addition, be sure to index the +'sudoUser' attribute. + +Three versions of the schema: one for OpenLDAP servers (F), +one for Netscape-derived servers (F), and one for +Microsoft Active Directory (F) may +be found in the B distribution. + +The schema for B in OpenLDAP form is included in the L +section. + +=head2 Configuring ldap.conf + +Sudo reads the F<@ldap_conf@> file for LDAP-specific configuration. +Typically, this file is shared amongst different LDAP-aware clients. +As such, most of the settings are not B-specific. Note that +B parses F<@ldap_conf@> itself and may support options +that differ from those described in the L manual. + +Also note that on systems using the OpenLDAP libraries, default +values specified in F or the user's +F<.ldaprc> files are not used. + +Only those options explicitly listed in F<@ldap_conf@> that are +supported by B are honored. Configuration options are listed +below in upper case but are parsed in a case-independent manner. + +=over 4 + +=item B ldap[s]://[hostname[:port]] ... + +Specifies a whitespace-delimited list of one or more URIs describing +the LDAP server(s) to connect to. The I may be either B +or B, the latter being for servers that support TLS (SSL) +encryption. If no I is specified, the default is port 389 for +C or port 636 for C. If no I is specified, +B will connect to B. Only systems using the OpenSSL +libraries support the mixing of C and C URIs. +The Netscape-derived libraries used on most commercial versions of +Unix are only capable of supporting one or the other. + +=item B name[:port] ... + +If no B is specified, the B parameter specifies a +whitespace-delimited list of LDAP servers to connect to. Each host +may include an optional I separated by a colon (':'). The +B parameter is deprecated in favor of the B specification +and is included for backwards compatibility. + +=item B port_number + +If no B is specified, the B parameter specifies the +default port to connect to on the LDAP server if a B parameter +does not specify the port itself. If no B parameter is used, +the default is port 389 for LDAP and port 636 for LDAP over TLS +(SSL). The B parameter is deprecated in favor of the B +specification and is included for backwards compatibility. + +=item B seconds + +The B parameter specifies the amount of time, in seconds, +to wait while trying to connect to an LDAP server. If multiple Bs or +Bs are specified, this is the amount of time to wait before trying +the next one in the list. + +=item B seconds + +The B parameter specifies the amount of time, in seconds, +to wait for a response to an LDAP query. + +=item B base + +The base DN to use when performing B LDAP queries. Typically +this is of the form C for the domain +C. + +=item B debug_level + +This sets the debug level for B LDAP queries. Debugging +information is printed to the standard error. A value of 1 results +in a moderate amount of debugging information. A value of 2 shows +the results of the matches themselves. This parameter should not +be set in a production environment as the extra information is +likely to confuse users. + +=item B DN + +The B parameter specifies the identity, in the form of a +Distinguished Name (DN), to use when performing LDAP operations. +If not specified, LDAP operations are performed with an anonymous +identity. By default, most LDAP servers will allow anonymous access. + +=item B secret + +The B parameter specifies the password to use when performing +LDAP operations. This is typically used in conjunction with the +B parameter. + +=item B DN + +The B parameter specifies the identity, in the form of +a Distinguished Name (DN), to use when performing privileged LDAP +operations, such as I queries. The password corresponding +to the identity should be stored in F<@ldap_secret@>. +If not specified, the B identity is used (if any). + +=item B number + +The version of the LDAP protocol to use when connecting to the server. +The default value is protocol version 3. + +=item B on/true/yes/off/false/no + +If the B parameter is set to C, C or C, TLS +(SSL) encryption is always used when communicating with the LDAP +server. Typically, this involves connecting to the server on port +636 (ldaps). + +=item B start_tls + +If the B parameter is set to C, the LDAP server +connection is initiated normally and TLS encryption is begun before +the bind credentials are sent. This has the advantage of not +requiring a dedicated port for encrypted communications. This +parameter is only supported by LDAP servers that honor the C +extension, such as the OpenLDAP server. + +=item B on/true/yes/off/false/no + +If enabled, B will cause the LDAP server's TLS +certificated to be verified. If the server's TLS certificate cannot +be verified (usually because it is signed by an unknown certificate +authority), B will be unable to connect to it. If B +is disabled, no check is made. + +=item B file name + +The path to a certificate authority bundle which contains the certificates +for all the Certificate Authorities the client knows to be valid, +e.g. F. +This option is only supported by the OpenLDAP libraries. + +=item B directory + +Similar to B but instead of a file, it is a +directory containing individual Certificate Authority certificates, +e.g. F. +The directory specified by B is checked after +B. +This option is only supported by the OpenLDAP libraries. + +=item B file name + +The path to a file containing the client certificate which can +be used to authenticate the client to the LDAP server. +The certificate type depends on the LDAP libraries used. + +OpenLDAP: + C + +Netscape-derived: + C + +When using Netscape-derived libraries, this file may also contain +Certificate Authority certificates. + +=item B file name + +The path to a file containing the private key which matches the +certificate specified by B. The private key must not be +password-protected. The key type depends on the LDAP libraries +used. + +OpenLDAP: + C + +Netscape-derived: + C + +=item B file name + +The B parameter specifies the path to an entropy +source for systems that lack a random device. It is generally used +in conjunction with I or I. +This option is only supported by the OpenLDAP libraries. + +=item B cipher list + +The B parameter allows the administer to restrict +which encryption algorithms may be used for TLS (SSL) connections. +See the OpenSSL manual for a list of valid ciphers. +This option is only supported by the OpenLDAP libraries. + +=item B on/true/yes/off/false/no + +Enable B for LDAP servers that support SASL authentication. + +=item B identity + +The SASL user name to use when connecting to the LDAP server. +By default, B will use an anonymous connection. + +=item B on/true/yes/off/false/no + +Enable B to enable SASL authentication when connecting +to an LDAP server from a privileged process, such as B. + +=item B identity + +The SASL user name to use when B is enabled. + +=item B none/properties + +SASL security properties or I for no properties. See the +SASL programmer's manual for details. + +=item B file name + +The path to the Kerberos 5 credential cache to use when authenticating +with the remote server. + +=back + +See the C entry in the L section. + +=head2 Configuring nsswitch.conf + +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 +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. + +The following sources are recognized: + + files read sudoers from F<@sysconfdir@/sudoers> + ldap read sudoers from LDAP + +In addition, the entry C<[NOTFOUND=return]> will short-circuit the +search if the user was not found in the preceding source. + +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 + +If the F<@nsswitch_conf@> file is not present or there is no +sudoers line, the following default is assumed: + + sudoers: files + +Note that F<@nsswitch_conf@> is supported even when the underlying +operating system does not use an nsswitch.conf file. + +=head1 FILES + +=over 24 + +=item F<@ldap_conf@> + +LDAP configuration file + +=item F<@nsswitch_conf@> + +determines sudoers source order + +=back + +=head1 EXAMPLES + +=head2 Example ldap.conf + + # Either specify one or more URIs or one or more host:port pairs. + # If neither is specified sudo will default to localhost, port 389. + # + #host ldapserver + #host ldapserver1 ldapserver2:390 + # + # Default port if host is specified without one, defaults to 389. + #port 389 + # + # URI will override the host and port settings. + uri ldap://ldapserver + #uri ldaps://secureldapserver + #uri ldaps://secureldapserver ldap://ldapserver + # + # The amount of time, in seconds, to wait while trying to connect to + # an LDAP server. + bind_timelimit 30 + # + # The amount of time, in seconds, to wait while performing an LDAP query. + timelimit 30 + # + # must be set or sudo will ignore LDAP + sudoers_base ou=SUDOers,dc=example,dc=com + # + # verbose sudoers matching from ldap + #sudoers_debug 2 + # + # optional proxy credentials + #binddn + #bindpw + #rootbinddn + # + # LDAP protocol version, defaults to 3 + #ldap_version 3 + # + # Define if you want to use an encrypted LDAP connection. + # Typically, you must also set the port to 636 (ldaps). + #ssl on + # + # Define if you want to use port 389 and switch to + # encryption before the bind credentials are sent. + # Only supported by LDAP servers that support the start_tls + # extension such as OpenLDAP. + #ssl start_tls + # + # Additional TLS options follow that allow tweaking of the + # SSL/TLS connection. + # + #tls_checkpeer yes # verify server SSL certificate + #tls_checkpeer no # ignore server SSL certificate + # + # If you enable tls_checkpeer, specify either tls_cacertfile + # or tls_cacertdir. Only supported when using OpenLDAP. + # + #tls_cacertfile /etc/certs/trusted_signers.pem + #tls_cacertdir /etc/certs + # + # For systems that don't have /dev/random + # use this along with PRNGD or EGD.pl to seed the + # random number pool to generate cryptographic session keys. + # Only supported when using OpenLDAP. + # + #tls_randfile /etc/egd-pool + # + # You may restrict which ciphers are used. Consult your SSL + # documentation for which options go here. + # Only supported when using OpenLDAP. + # + #tls_ciphers + # + # Sudo can provide a client certificate when communicating to + # the LDAP server. + # Tips: + # * Enable both lines at the same time. + # * Do not password protect the key file. + # * Ensure the keyfile is only readable by root. + # + # For OpenLDAP: + #tls_cert /etc/certs/client_cert.pem + #tls_key /etc/certs/client_key.pem + # + # For 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 + # + # If using SASL authentication for LDAP (OpenSSL) + # use_sasl yes + # sasl_auth_id + # rootuse_sasl yes + # rootsasl_auth_id + # sasl_secprops none + # krb5_ccname /etc/.ldapcache + +=head2 Sudo schema for OpenLDAP + +The following schema is in OpenLDAP format. Simply copy it to the +schema directory (e.g. F), add the proper +C line in C and restart B. + + attributetype ( 1.3.6.1.4.1.15953.9.1.1 + NAME 'sudoUser' + DESC 'User(s) who may run sudo' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.2 + NAME 'sudoHost' + DESC 'Host(s) who may run sudo' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.3 + NAME 'sudoCommand' + DESC 'Command(s) to be executed by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.4 + NAME 'sudoRunAs' + DESC 'User(s) impersonated by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.5 + NAME 'sudoOption' + DESC 'Options(s) followed by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.6 + NAME 'sudoRunAsUser' + DESC 'User(s) impersonated by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + attributetype ( 1.3.6.1.4.1.15953.9.1.7 + NAME 'sudoRunAsGroup' + DESC 'Group(s) impersonated by sudo' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL + DESC 'Sudoer Entries' + MUST ( cn ) + MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ + sudoRunAsGroup $ sudoOption $ description ) + ) + +=for comment + +Add nsswitch.conf example? +Add more exhaustive sudoers ldif example? + +=head1 SEE ALSO + +L, L + +=head1 CAVEATS + +The way that I is parsed differs between Note that there +are differences in the way that LDAP-based I is parsed +compared to file-based I. See the L section for more information. + +=head1 BUGS + +If you feel you have found a bug in B, please submit a bug report +at http://www.sudo.ws/sudo/bugs/ + +=head1 SUPPORT + +Limited free support is available via the sudo-users mailing list, +see http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or +search the archives. + +=head1 DISCLAIMER + +B is provided ``AS IS'' and any express or implied warranties, +including, but not limited to, the implied warranties of merchantability +and fitness for a particular purpose are disclaimed. See the LICENSE +file distributed with B or http://www.sudo.ws/sudo/license.html +for complete details. diff --git a/sudoers.man.in b/sudoers.man.in index 9184006..533c8c7 100644 --- a/sudoers.man.in +++ b/sudoers.man.in @@ -1,4 +1,4 @@ -.\" Copyright (c) 1994-1996, 1998-2005, 2007 +.\" Copyright (c) 1994-1996, 1998-2005, 2007-2008 .\" Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -18,8 +18,8 @@ .\" 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.45.2.29 2008/06/22 20:29:03 millert Exp $ -.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 +.\" $Sudo: sudoers.man.in,v 1.74 2008/12/03 20:58:41 millert Exp $ +.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.05) .\" .\" Standard preamble: .\" ======================================================================== @@ -46,11 +46,11 @@ .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. | will give a -.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to -.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' -.\" expand to `' in nroff, nothing in troff, for use with C<>. -.tr \(*W-|\(bv\*(Tr +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- @@ -69,22 +69,25 @@ . ds R" '' 'br\} .\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. -.if \nF \{\ +.ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} -.\" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.hy 0 -.if n .na +.el \{\ +. de IX +.. +.\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -150,7 +153,11 @@ .\" ======================================================================== .\" .IX Title "SUDOERS @mansectform@" -.TH SUDOERS @mansectform@ "Jun 21, 2008" "1.6.9p17" "MAINTENANCE COMMANDS" +.TH SUDOERS @mansectform@ "December 3, 2008" "1.7.0" "MAINTENANCE COMMANDS" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh .SH "NAME" sudoers \- list of which users may execute what .SH "DESCRIPTION" @@ -205,30 +212,20 @@ There are four kinds of aliases: \f(CW\*(C`User_Alias\*(C'\fR, \f(CW\*(C`Runas_A \&\f(CW\*(C`Host_Alias\*(C'\fR and \f(CW\*(C`Cmnd_Alias\*(C'\fR. .PP .Vb 4 -\& Alias ::= 'User_Alias' User_Alias (':' User_Alias)* | -\& 'Runas_Alias' Runas_Alias (':' Runas_Alias)* | -\& 'Host_Alias' Host_Alias (':' Host_Alias)* | -\& 'Cmnd_Alias' Cmnd_Alias (':' Cmnd_Alias)* -.Ve -.PP -.Vb 1 -\& User_Alias ::= NAME '=' User_List -.Ve -.PP -.Vb 1 -\& Runas_Alias ::= NAME '=' Runas_List -.Ve -.PP -.Vb 1 -\& Host_Alias ::= NAME '=' Host_List -.Ve -.PP -.Vb 1 -\& Cmnd_Alias ::= NAME '=' Cmnd_List -.Ve -.PP -.Vb 1 -\& NAME ::= [A-Z]([A-Z][0-9]_)* +\& Alias ::= \*(AqUser_Alias\*(Aq User_Alias (\*(Aq:\*(Aq User_Alias)* | +\& \*(AqRunas_Alias\*(Aq Runas_Alias (\*(Aq:\*(Aq Runas_Alias)* | +\& \*(AqHost_Alias\*(Aq Host_Alias (\*(Aq:\*(Aq Host_Alias)* | +\& \*(AqCmnd_Alias\*(Aq Cmnd_Alias (\*(Aq:\*(Aq Cmnd_Alias)* +\& +\& User_Alias ::= NAME \*(Aq=\*(Aq User_List +\& +\& Runas_Alias ::= NAME \*(Aq=\*(Aq Runas_List +\& +\& Host_Alias ::= NAME \*(Aq=\*(Aq Host_List +\& +\& Cmnd_Alias ::= NAME \*(Aq=\*(Aq Cmnd_List +\& +\& NAME ::= [A\-Z]([A\-Z][0\-9]_)* .Ve .PP Each \fIalias\fR definition is of the form @@ -251,54 +248,48 @@ The definitions of what constitutes a valid \fIalias\fR member follow. .PP .Vb 2 \& User_List ::= User | -\& User ',' User_List -.Ve -.PP -.Vb 4 -\& User ::= '!'* username | -\& '!'* '%'group | -\& '!'* '+'netgroup | -\& '!'* User_Alias +\& User \*(Aq,\*(Aq User_List +\& +\& User ::= \*(Aq!\*(Aq* username | +\& \*(Aq!\*(Aq* \*(Aq#\*(Aquid | +\& \*(Aq!\*(Aq* \*(Aq%\*(Aqgroup | +\& \*(Aq!\*(Aq* \*(Aq+\*(Aqnetgroup | +\& \*(Aq!\*(Aq* User_Alias .Ve .PP -A \f(CW\*(C`User_List\*(C'\fR is made up of one or more usernames, system groups -(prefixed with '%'), netgroups (prefixed with '+') and other aliases. -Each list item may be prefixed with one or more '!' operators. -An odd number of '!' operators negate the value of the item; an even -number just cancel each other out. +A \f(CW\*(C`User_List\*(C'\fR is made up of one or more usernames, uids (prefixed +with '#'), system groups (prefixed with '%'), netgroups (prefixed +with '+') and \f(CW\*(C`User_Alias\*(C'\fRes. 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. .PP .Vb 2 -\& Runas_List ::= Runas_User | -\& Runas_User ',' Runas_List +\& Runas_List ::= Runas_Member | +\& Runas_Member \*(Aq,\*(Aq Runas_List +\& +\& Runas_Member ::= \*(Aq!\*(Aq* username | +\& \*(Aq!\*(Aq* \*(Aq#\*(Aquid | +\& \*(Aq!\*(Aq* \*(Aq%\*(Aqgroup | +\& \*(Aq!\*(Aq* +netgroup | +\& \*(Aq!\*(Aq* Runas_Alias .Ve .PP -.Vb 5 -\& Runas_User ::= '!'* username | -\& '!'* '#'uid | -\& '!'* '%'group | -\& '!'* +netgroup | -\& '!'* Runas_Alias -.Ve -.PP -A \f(CW\*(C`Runas_List\*(C'\fR is similar to a \f(CW\*(C`User_List\*(C'\fR except that it can -also contain uids (prefixed with '#') and instead of \f(CW\*(C`User_Alias\*(C'\fRes -it can contain \f(CW\*(C`Runas_Alias\*(C'\fRes. Note that usernames and groups -are matched as strings. In other words, two users (groups) with -the same uid (gid) are considered to be distinct. If you wish to -match all usernames with the same uid (e.g.\ root and toor), you -can use a uid instead (#0 in the example given). +A \f(CW\*(C`Runas_List\*(C'\fR is similar to a \f(CW\*(C`User_List\*(C'\fR except that instead +of \f(CW\*(C`User_Alias\*(C'\fRes it can contain \f(CW\*(C`Runas_Alias\*(C'\fRes. Note that +usernames and groups are matched as strings. In other words, two +users (groups) with the same uid (gid) are considered to be distinct. +If you wish to match all usernames with the same uid (e.g.\ root +and toor), you can use a uid instead (#0 in the example given). .PP .Vb 2 \& Host_List ::= Host | -\& Host ',' Host_List -.Ve -.PP -.Vb 5 -\& Host ::= '!'* hostname | -\& '!'* ip_addr | -\& '!'* network(/netmask)? | -\& '!'* '+'netgroup | -\& '!'* Host_Alias +\& Host \*(Aq,\*(Aq Host_List +\& +\& Host ::= \*(Aq!\*(Aq* hostname | +\& \*(Aq!\*(Aq* ip_addr | +\& \*(Aq!\*(Aq* network(/netmask)? | +\& \*(Aq!\*(Aq* \*(Aq+\*(Aqnetgroup | +\& \*(Aq!\*(Aq* Host_Alias .Ve .PP A \f(CW\*(C`Host_List\*(C'\fR is made up of one or more hostnames, \s-1IP\s0 addresses, @@ -318,20 +309,16 @@ wildcards to be useful. .PP .Vb 2 \& Cmnd_List ::= Cmnd | -\& Cmnd ',' Cmnd_List -.Ve -.PP -.Vb 3 +\& Cmnd \*(Aq,\*(Aq Cmnd_List +\& \& commandname ::= filename | \& filename args | -\& filename '""' -.Ve -.PP -.Vb 4 -\& Cmnd ::= '!'* commandname | -\& '!'* directory | -\& '!'* "sudoedit" | -\& '!'* Cmnd_Alias +\& filename \*(Aq""\*(Aq +\& +\& Cmnd ::= \*(Aq!\*(Aq* commandname | +\& \*(Aq!\*(Aq* directory | +\& \*(Aq!\*(Aq* "sudoedit" | +\& \*(Aq!\*(Aq* Cmnd_Alias .Ve .PP A \f(CW\*(C`Cmnd_List\*(C'\fR is a list of one or more commandnames, directories, and other @@ -350,7 +337,7 @@ in the \f(CW\*(C`Cmnd\*(C'\fR must match exactly those given by the user on the (or match the wildcards if there are any). Note that the following characters must be escaped with a '\e' if they are used in command arguments: ',', ':', '=', '\e'. The special command \f(CW"sudoedit"\fR -is used to permit a user to run \fBsudo\fR with the \fB\-e\fR flag (or +is used to permit a user to run \fBsudo\fR with the \fB\-e\fR option (or as \fBsudoedit\fR). It may take command line arguments just as a normal command does. .Sh "Defaults" @@ -358,29 +345,27 @@ a normal command does. Certain configuration options may be changed from their default values at runtime via one or more \f(CW\*(C`Default_Entry\*(C'\fR lines. These may affect all users on any host, all users on a specific host, a -specific user, or commands being run as a specific user. +specific user, a specific command, or commands being run as a specific user. +Note that per-command entries may not include command line arguments. +If you need to specify arguments, define a \f(CW\*(C`Cmnd_Alias\*(C'\fR and reference +that instead. .PP -.Vb 4 -\& Default_Type ::= 'Defaults' | -\& 'Defaults' '@' Host_List | -\& 'Defaults' ':' User_List | -\& 'Defaults' '>' Runas_List -.Ve -.PP -.Vb 1 +.Vb 5 +\& Default_Type ::= \*(AqDefaults\*(Aq | +\& \*(AqDefaults\*(Aq \*(Aq@\*(Aq Host_List | +\& \*(AqDefaults\*(Aq \*(Aq:\*(Aq User_List | +\& \*(AqDefaults\*(Aq \*(Aq!\*(Aq Cmnd_List | +\& \*(AqDefaults\*(Aq \*(Aq>\*(Aq Runas_List +\& \& Default_Entry ::= Default_Type Parameter_List -.Ve -.PP -.Vb 2 +\& \& Parameter_List ::= Parameter | -\& Parameter ',' Parameter_List -.Ve -.PP -.Vb 4 -\& Parameter ::= Parameter '=' Value | -\& Parameter '+=' Value | -\& Parameter '-=' Value | -\& '!'* Parameter +\& Parameter \*(Aq,\*(Aq Parameter_List +\& +\& Parameter ::= Parameter \*(Aq=\*(Aq Value | +\& Parameter \*(Aq+=\*(Aq Value | +\& Parameter \*(Aq\-=\*(Aq Value | +\& \*(Aq!\*(Aq* Parameter .Ve .PP Parameters may be \fBflags\fR, \fBinteger\fR values, \fBstrings\fR, or \fBlists\fR. @@ -395,30 +380,26 @@ These operators are used to add to and delete from a list respectively. It is not an error to use the \f(CW\*(C`\-=\*(C'\fR operator to remove an element that does not exist in a list. .PP +Defaults entries are parsed in the following order: generic, host +and user Defaults first, then runas Defaults and finally command +defaults. +.PP See \*(L"\s-1SUDOERS\s0 \s-1OPTIONS\s0\*(R" for a list of supported Defaults parameters. .Sh "User Specification" .IX Subsection "User Specification" .Vb 2 -\& User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \e -\& (':' Host_List '=' Cmnd_Spec_List)* -.Ve -.PP -.Vb 2 +\& User_Spec ::= User_List Host_List \*(Aq=\*(Aq Cmnd_Spec_List \e +\& (\*(Aq:\*(Aq Host_List \*(Aq=\*(Aq Cmnd_Spec_List)* +\& \& Cmnd_Spec_List ::= Cmnd_Spec | -\& Cmnd_Spec ',' Cmnd_Spec_List -.Ve -.PP -.Vb 1 +\& Cmnd_Spec \*(Aq,\*(Aq Cmnd_Spec_List +\& \& Cmnd_Spec ::= Runas_Spec? Tag_Spec* Cmnd -.Ve -.PP -.Vb 1 -\& Runas_Spec ::= '(' Runas_List ')' -.Ve -.PP -.Vb 2 -\& Tag_Spec ::= ('NOPASSWD:' | 'PASSWD:' | 'NOEXEC:' | 'EXEC:' | -\& 'SETENV:' | 'NOSETENV:') +\& +\& Runas_Spec ::= \*(Aq(\*(Aq Runas_List? (: Runas_List)? \*(Aq)\*(Aq +\& +\& Tag_Spec ::= (\*(AqNOPASSWD:\*(Aq | \*(AqPASSWD:\*(Aq | \*(AqNOEXEC:\*(Aq | \*(AqEXEC:\*(Aq | +\& \*(AqSETENV:\*(Aq | \*(AqNOSETENV:\*(Aq ) .Ve .PP A \fBuser specification\fR determines which commands a user may run @@ -428,11 +409,24 @@ run as \fBroot\fR, but this can be changed on a per-command basis. Let's break that down into its constituent parts: .Sh "Runas_Spec" .IX Subsection "Runas_Spec" -A \f(CW\*(C`Runas_Spec\*(C'\fR is simply a \f(CW\*(C`Runas_List\*(C'\fR (as defined above) -enclosed in a set of parentheses. If you do not specify a -\&\f(CW\*(C`Runas_Spec\*(C'\fR in the user specification, a default \f(CW\*(C`Runas_Spec\*(C'\fR -of \fBroot\fR will be used. A \f(CW\*(C`Runas_Spec\*(C'\fR sets the default for -commands that follow it. What this means is that for the entry: +A \f(CW\*(C`Runas_Spec\*(C'\fR determines the user and/or the group that a command +may be run as. A fully-specified \f(CW\*(C`Runas_Spec\*(C'\fR consists of two +\&\f(CW\*(C`Runas_List\*(C'\fRs (as defined above) separated by a colon (':') and +enclosed in a set of parentheses. The first \f(CW\*(C`Runas_List\*(C'\fR indicates +which users the command may be run as via \fBsudo\fR's \fB\-u\fR option. +The second defines a list of groups that can be specified via +\&\fBsudo\fR's \fB\-g\fR option. If both \f(CW\*(C`Runas_List\*(C'\fRs are specified, the +command may be run with any combination of users and groups listed +in their respective \f(CW\*(C`Runas_List\*(C'\fRs. If only the first is specified, +the command may be run as any user in the list but no \fB\-g\fR option +may be specified. If the first \f(CW\*(C`Runas_List\*(C'\fR is empty but the +second is specified, the command may be run as the invoking user +with the group set to any listed in the \f(CW\*(C`Runas_List\*(C'\fR. If no +\&\f(CW\*(C`Runas_Spec\*(C'\fR is specified the command may be run as \fBroot\fR and +no group may be specified. +.PP +A \f(CW\*(C`Runas_Spec\*(C'\fR sets the default for the commands that follow it. +What this means is that for the entry: .PP .Vb 1 \& dgb boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm @@ -442,7 +436,7 @@ The user \fBdgb\fR may run \fI/bin/ls\fR, \fI/bin/kill\fR, and \&\fI/usr/bin/lprm\fR \*(-- but only as \fBoperator\fR. E.g., .PP .Vb 1 -\& $ sudo -u operator /bin/ls. +\& $ sudo \-u operator /bin/ls. .Ve .PP It is also possible to override a \f(CW\*(C`Runas_Spec\*(C'\fR later on in an @@ -454,10 +448,27 @@ entry. If we modify the entry like so: .PP Then user \fBdgb\fR is now allowed to run \fI/bin/ls\fR as \fBoperator\fR, but \fI/bin/kill\fR and \fI/usr/bin/lprm\fR as \fBroot\fR. +.PP +We can extend this to allow \fBdgb\fR to run \f(CW\*(C`/bin/ls\*(C'\fR with either +the user or group set to \fBoperator\fR: +.PP +.Vb 2 +\& dgb boulder = (operator : operator) /bin/ls, (root) /bin/kill, \e +\& /usr/bin/lprm +.Ve +.PP +In the following example, user \fBtcm\fR may run commands that access +a modem device file with the dialer group. Note that in this example +only the group will be set, the command still runs as user \fBtcm\fR. +.PP +.Vb 2 +\& tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu, \e +\& /usr/local/bin/minicom +.Ve .Sh "Tag_Spec" .IX Subsection "Tag_Spec" A command may have zero or more tags associated with it. There are -six possible tag values, \f(CW\*(C`NOPASSWD\*(C'\fR, \f(CW\*(C`PASSWD\*(C'\fR, \f(CW\*(C`NOEXEC\*(C'\fR, \f(CW\*(C`EXEC\*(C'\fR, +eight possible tag values, \f(CW\*(C`NOPASSWD\*(C'\fR, \f(CW\*(C`PASSWD\*(C'\fR, \f(CW\*(C`NOEXEC\*(C'\fR, \f(CW\*(C`EXEC\*(C'\fR, \&\f(CW\*(C`SETENV\*(C'\fR and \f(CW\*(C`NOSETENV\*(C'\fR. Once a tag is set on a \f(CW\*(C`Cmnd\*(C'\fR, subsequent \f(CW\*(C`Cmnd\*(C'\fRs in the \&\f(CW\*(C`Cmnd_Spec_List\*(C'\fR, inherit the tag unless it is overridden by the @@ -479,7 +490,7 @@ For example: .Ve .PP would allow the user \fBray\fR to run \fI/bin/kill\fR, \fI/bin/ls\fR, and -\&\fI/usr/bin/lprm\fR as root on the machine rushmore as \fBroot\fR without +\&\fI/usr/bin/lprm\fR as \fBroot\fR on the machine rushmore without authenticating himself. If we only want \fBray\fR to be able to run \fI/bin/kill\fR without a password the entry would be: .PP @@ -528,7 +539,7 @@ 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 pathnames as well as command line arguments in the +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. .ie n .IP "\*(C`*\*(C'" 8 @@ -553,6 +564,17 @@ 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: +.PP +.Vb 1 +\& /bin/ls [[\e:alpha\e:]]* +.Ve +.PP +Would match any filename beginning with a letter. +.PP Note that a forward slash ('/') will \fBnot\fR be matched by wildcards used in the pathname. When matching the command line arguments, however, a slash \fBdoes\fR get matched by @@ -572,6 +594,27 @@ The following exceptions apply to the above rules: If the empty string \f(CW""\fR is the only command line argument in the \&\fIsudoers\fR entry it means that command is not allowed to be run 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 +.PP +When \fBsudo\fR reaches this line it will suspend processing of the +current file (\fI/etc/sudoers\fR) and switch to \fI/etc/sudoers.local\fR. +Upon reaching the end of \fI/etc/sudoers.local\fR, the rest of +\&\fI/etc/sudoers\fR will be processed. Files that are included may +themselves include other files. A hard limit of 128 nested include +files is enforced to prevent include file loops. .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 @@ -615,7 +658,7 @@ grouped by type, are listed below. .IX Item "always_set_home" If set, \fBsudo\fR will set the \f(CW\*(C`HOME\*(C'\fR environment variable to the home directory of the target user (which is root unless the \fB\-u\fR option is used). -This effectively means that the \fB\-H\fR flag is always implied. +This effectively means that the \fB\-H\fR option is always implied. This flag is \fIoff\fR by default. .IP "authenticate" 16 .IX Item "authenticate" @@ -623,6 +666,11 @@ If set, users must authenticate themselves via a password (or other means of authentication) before they may run commands. This default may be overridden via the \f(CW\*(C`PASSWD\*(C'\fR and \f(CW\*(C`NOPASSWD\*(C'\fR tags. This flag is \fIon\fR by default. +.IP "closefrom_override" 16 +.IX Item "closefrom_override" +If set, the user may use \fBsudo\fR's \fB\-C\fR option which +overrides the default starting point at which \fBsudo\fR begins +closing open file descriptors. This flag is \fIoff\fR by default. .IP "env_editor" 16 .IX Item "env_editor" If set, \fBvisudo\fR will use the value of the \s-1EDITOR\s0 or \s-1VISUAL\s0 @@ -640,9 +688,9 @@ If set, \fBsudo\fR will reset the environment to only contain the variables in the caller's environment that match the \f(CW\*(C`env_keep\*(C'\fR and \f(CW\*(C`env_check\*(C'\fR lists are then added. The default contents of the \&\f(CW\*(C`env_keep\*(C'\fR and \f(CW\*(C`env_check\*(C'\fR lists are displayed when \fBsudo\fR is -run by root with the \fI\-V\fR option. If \fBsudo\fR was compiled with -the \f(CW\*(C`SECURE_PATH\*(C'\fR option, its value will be used for the \f(CW\*(C`PATH\*(C'\fR -environment variable. This flag is \fIon\fR by default. +run by root with the \fI\-V\fR option. If the \fIsecure_path\fR option +is set, its value will be used for the \f(CW\*(C`PATH\*(C'\fR environment variable. +This flag is \fIon\fR by default. .IP "fqdn" 16 .IX Item "fqdn" Set this flag if you want to put fully qualified hostnames in the @@ -661,10 +709,7 @@ command) is already fully qualified you shouldn't need to set .IX Item "ignore_dot" If set, \fBsudo\fR will ignore '.' or '' (current dir) in the \f(CW\*(C`PATH\*(C'\fR environment variable; the \f(CW\*(C`PATH\*(C'\fR itself is not modified. This -flag is \fI@ignore_dot@\fR by default. Currently, while it is possible -to set \fIignore_dot\fR in \fIsudoers\fR, its value is not used. This option -should be considered read-only (it will be fixed in a future version -of \fBsudo\fR). +flag is \fI@ignore_dot@\fR by default. .IP "ignore_local_sudoers" 16 .IX Item "ignore_local_sudoers" If set via \s-1LDAP\s0, parsing of \fI@sysconfdir@/sudoers\fR will be skipped. @@ -681,11 +726,11 @@ If set, \fBsudo\fR will insult users when they enter an incorrect password. This flag is \fI@insults@\fR by default. .IP "log_host" 16 .IX Item "log_host" -If set, the hostname will be logged in the (non\-syslog) \fBsudo\fR log file. +If set, the hostname will be logged in the (non-syslog) \fBsudo\fR log file. This flag is \fIoff\fR by default. .IP "log_year" 16 .IX Item "log_year" -If set, the four-digit year will be logged in the (non\-syslog) \fBsudo\fR log file. +If set, the four-digit year will be logged in the (non-syslog) \fBsudo\fR log file. This flag is \fIoff\fR by default. .IP "long_otp_prompt" 16 .IX Item "long_otp_prompt" @@ -722,7 +767,8 @@ by default. .IX Item "noexec" If set, all commands run via \fBsudo\fR will behave as if the \f(CW\*(C`NOEXEC\*(C'\fR tag has been set, unless overridden by a \f(CW\*(C`EXEC\*(C'\fR tag. See the -description of \fI\s-1NOEXEC\s0 and \s-1EXEC\s0\fR below as well as the \*(L"\s-1PREVENTING\s0 \s-1SHELL\s0 \s-1ESCAPES\s0\*(R" section at the end of this manual. This flag is \fIoff\fR by default. +description of \fI\s-1NOEXEC\s0 and \s-1EXEC\s0\fR below as well as the \*(L"\s-1PREVENTING\s0 \s-1SHELL\s0 +\&\s-1ESCAPES\s0\*(R" section at the end of this manual. This flag is \fIoff\fR by default. .IP "path_info" 16 .IX Item "path_info" Normally, \fBsudo\fR will tell the user when a command could not be @@ -749,11 +795,9 @@ user. 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 -tty. This will disallow things like \f(CW"rsh somehost sudo ls"\fR since -\&\fIrsh\fR\|(1) does not allocate a tty. Because it is not possible to turn -off echo when there is no tty present, some sites may wish to set -this flag to prevent a user from entering a visible password. This -flag is \fIoff\fR by default. +tty. When this flag is set, \fBsudo\fR can only be run from a login +session and not via other means such as \fIcron\fR\|(@mansectsu@) or cgi-bin scripts. +This flag is \fIoff\fR by default. .IP "root_sudo" 16 .IX Item "root_sudo" If set, root is allowed to run \fBsudo\fR too. Disabling this prevents users @@ -774,15 +818,15 @@ If set, \fBsudo\fR will prompt for the password of the user defined by the password of the invoking user. This flag is \fIoff\fR by default. .IP "set_home" 16 .IX Item "set_home" -If set and \fBsudo\fR is invoked with the \fB\-s\fR flag the \f(CW\*(C`HOME\*(C'\fR +If set and \fBsudo\fR is invoked with the \fB\-s\fR option the \f(CW\*(C`HOME\*(C'\fR environment variable will be set to the home directory of the target user (which is root unless the \fB\-u\fR option is used). This effectively -makes the \fB\-s\fR flag imply \fB\-H\fR. This flag is \fIoff\fR by default. +makes the \fB\-s\fR option imply \fB\-H\fR. This flag is \fIoff\fR by default. .IP "set_logname" 16 .IX Item "set_logname" Normally, \fBsudo\fR will set the \f(CW\*(C`LOGNAME\*(C'\fR, \f(CW\*(C`USER\*(C'\fR and \f(CW\*(C`USERNAME\*(C'\fR environment variables to the name of the target user (usually root -unless the \fB\-u\fR flag is given). However, since some programs +unless the \fB\-u\fR option is given). However, since some programs (including the \s-1RCS\s0 revision control system) use \f(CW\*(C`LOGNAME\*(C'\fR to determine the real identity of the user, it may be desirable to change this behavior. This can be done by negating the set_logname @@ -800,7 +844,7 @@ by default. .IP "shell_noargs" 16 .IX Item "shell_noargs" If set and \fBsudo\fR is invoked with no arguments it acts as if the -\&\fB\-s\fR flag had been given. That is, it runs a shell as root (the +\&\fB\-s\fR option had been given. That is, it runs a shell as root (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. @@ -817,9 +861,9 @@ function. This flag is \fIoff\fR by default. .IP "targetpw" 16 .IX Item "targetpw" If set, \fBsudo\fR will prompt for the password of the user specified by -the \fB\-u\fR flag (defaults to \f(CW\*(C`root\*(C'\fR) instead of the password of the +the \fB\-u\fR option (defaults to \f(CW\*(C`root\*(C'\fR) 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 \fB\-u\fR flag. +in the passwd database as an argument to the \fB\-u\fR option. This flag is \fIoff\fR by default. .IP "tty_tickets" 16 .IX Item "tty_tickets" @@ -833,8 +877,23 @@ This flag is \fI@tty_tickets@\fR by default. @LCMAN@If set, \fBsudo\fR will apply the defaults specified for the target user's @LCMAN@login class if one exists. Only available if \fBsudo\fR is configured with @LCMAN@the \-\-with\-logincap option. This flag is \fIoff\fR by default. +.IP "visiblepw" 16 +.IX Item "visiblepw" +By default, \fBsudo\fR will refuse to run if the user must enter a +password but it is not possible to disable echo on the terminal. +If the \fIvisiblepw\fR flag is set, \fBsudo\fR will prompt for a password +even when it would be visible on the screen. This makes it possible +to run things like \f(CW"rsh somehost sudo ls"\fR since \fIrsh\fR\|(1) does +not allocate a tty. This flag is \fIoff\fR by default. .PP \&\fBIntegers\fR: +.IP "closefrom" 16 +.IX Item "closefrom" +Before it executes a command, \fBsudo\fR will close all open file +descriptors other than standard input, standard output and standard +error (ie: file descriptors 0\-2). The \fIclosefrom\fR option can be used +to specify a different file descriptor at which to start closing. +The default is \f(CW3\fR. .IP "passwd_tries" 16 .IX Item "passwd_tries" The number of tries a user gets to enter his/her password before @@ -862,7 +921,12 @@ own timestamps via \f(CW\*(C`sudo \-v\*(C'\fR and \f(CW\*(C`sudo \-k\*(C'\fR res .IP "umask" 16 .IX Item "umask" Umask to use when running the command. Negate this option or set -it to 0777 to preserve the user's umask. The default is \f(CW\*(C`@sudo_umask@\*(C'\fR. +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 \f(CW\*(C`@sudo_umask@\*(C'\fR. +This guarantees that \fBsudo\fR never lowers the umask when running a +command. Note on systems that use \s-1PAM\s0, the default \s-1PAM\s0 configuration +may specify its own umask which will override the value set in +\&\fIsudoers\fR. .PP \&\fBStrings\fR: .IP "badpass_message" 16 @@ -934,7 +998,7 @@ The default value is \f(CW\*(C`@passprompt@\*(C'\fR. @SEMAN@This option is only available whe \fBsudo\fR is built with SELinux support. .IP "runas_default" 16 .IX Item "runas_default" -The default user to run commands as if the \fB\-u\fR flag is not specified +The default user to run commands as if the \fB\-u\fR option is not specified on the command line. This defaults to \f(CW\*(C`@runas_default@\*(C'\fR. Note that if \fIrunas_default\fR is set it \fBmust\fR occur before any \f(CW\*(C`Runas_Alias\*(C'\fR specifications. @@ -946,6 +1010,11 @@ Defaults to \f(CW\*(C`@badpri@\*(C'\fR. .IX Item "syslog_goodpri" Syslog priority to use when user authenticates successfully. Defaults to \f(CW\*(C`@goodpri@\*(C'\fR. +.IP "sudoers_locale" 16 +.IX Item "sudoers_locale" +Locale to use when parsing the sudoers file. Note that changing +the locale may affect how sudoers is interpreted. +Defaults to \f(CW"C"\fR. .IP "timestampdir" 16 .IX Item "timestampdir" The directory in which \fBsudo\fR stores its timestamp files. @@ -962,6 +1031,23 @@ The default is \f(CW\*(C`root\*(C'\fR. @SEMAN@This option is only available whe \fBsudo\fR is built with SELinux support. .PP \&\fBStrings that can be used in a boolean context\fR: +.IP "askpass" 12 +.IX Item "askpass" +The \fIaskpass\fR option specifies the fully qualified path to a helper +program used to read the user's password when no terminal is +available. This may be the case when \fBsudo\fR is executed from a +graphical (as opposed to text-based) application. The program +specified by \fIaskpass\fR should display the argument passed to it +as the prompt and write the user's password to the standard output. +The value of \fIaskpass\fR may be overridden by the \f(CW\*(C`SUDO_ASKPASS\*(C'\fR +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. .IP "exempt_group" 12 .IX Item "exempt_group" Users in this group are exempt from password and \s-1PATH\s0 requirements. @@ -995,7 +1081,7 @@ By default, \fBsudo\fR uses a built-in lecture. .IP "listpw" 12 .IX Item "listpw" This option controls when a password will be required when a -user runs \fBsudo\fR with the \fB\-l\fR flag. It has the following possible values: +user runs \fBsudo\fR with the \fB\-l\fR option. It has the following possible values: .RS 12 .IP "all" 8 .IX Item "all" @@ -1003,14 +1089,14 @@ All the user's \fIsudoers\fR entries for the current host must have the \f(CW\*(C`NOPASSWD\*(C'\fR flag set to avoid entering a password. .IP "always" 8 .IX Item "always" -The user must always enter a password to use the \fB\-l\fR flag. +The user must always enter a password to use the \fB\-l\fR option. .IP "any" 8 .IX Item "any" At least one of the user's \fIsudoers\fR entries for the current host must have the \f(CW\*(C`NOPASSWD\*(C'\fR flag set to avoid entering a password. .IP "never" 8 .IX Item "never" -The user need never enter a password to use the \fB\-l\fR flag. +The user need never enter a password to use the \fB\-l\fR option. .RE .RS 12 .Sp @@ -1030,11 +1116,25 @@ Flags to use when invoking mailer. Defaults to \fB\-t\fR. .IX Item "mailerpath" Path to mail program used to send warning mail. Defaults to the path to sendmail found at configure time. +.IP "mailfrom" 12 +.IX Item "mailfrom" +Address to use for the \*(L"from\*(R" address when sending warning and error +mail. The address should be enclosed in double quotes (\f(CW\*(C`"\*(C'\fR) to +protect against \fBsudo\fR interpreting the \f(CW\*(C`@\*(C'\fR sign. Defaults to +the name of the user running \fBsudo\fR. .IP "mailto" 12 .IX Item "mailto" Address to send warning and error mail to. The address should be enclosed in double quotes (\f(CW\*(C`"\*(C'\fR) to protect against \fBsudo\fR interpreting the \f(CW\*(C`@\*(C'\fR sign. Defaults to \f(CW\*(C`@mailto@\*(C'\fR. +.IP "secure_path" 12 +.IX Item "secure_path" +Path used for every command run from \fBsudo\fR. If you don't trust the +people running \fBsudo\fR to have a sane \f(CW\*(C`PATH\*(C'\fR environment variable you may +want to use this. Another use is if you want to have the \*(L"root path\*(R" +be separate from the \*(L"user path.\*(R" Users in the group specified by the +\&\fIexempt_group\fR option are not affected by \fIsecure_path\fR. +This is not set by default. .IP "syslog" 12 .IX Item "syslog" Syslog facility if syslog is being used for logging (negate to @@ -1042,7 +1142,7 @@ disable syslog logging). Defaults to \f(CW\*(C`@logfac@\*(C'\fR. .IP "verifypw" 12 .IX Item "verifypw" This option controls when a password will be required when a user runs -\&\fBsudo\fR with the \fB\-v\fR flag. It has the following possible values: +\&\fBsudo\fR with the \fB\-v\fR option. It has the following possible values: .RS 12 .IP "all" 8 .IX Item "all" @@ -1050,14 +1150,14 @@ All the user's \fIsudoers\fR entries for the current host must have the \f(CW\*(C`NOPASSWD\*(C'\fR flag set to avoid entering a password. .IP "always" 8 .IX Item "always" -The user must always enter a password to use the \fB\-v\fR flag. +The user must always enter a password to use the \fB\-v\fR option. .IP "any" 8 .IX Item "any" At least one of the user's \fIsudoers\fR entries for the current host must have the \f(CW\*(C`NOPASSWD\*(C'\fR flag set to avoid entering a password. .IP "never" 8 .IX Item "never" -The user need never enter a password to use the \fB\-v\fR flag. +The user need never enter a password to use the \fB\-v\fR option. .RE .RS 12 .Sp @@ -1072,8 +1172,8 @@ The default value is \fIall\fR. Environment variables to be removed from the user's environment if the variable's value contains \f(CW\*(C`%\*(C'\fR or \f(CW\*(C`/\*(C'\fR characters. This can be used to guard against printf-style format vulnerabilities in -poorly-written programs. The argument may be a double\-quoted, -space-separated list or a single value without double\-quotes. The +poorly-written programs. 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. Regardless of whether the \f(CW\*(C`env_reset\*(C'\fR option is enabled or disabled, variables @@ -1084,8 +1184,8 @@ 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 +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 @@ -1097,8 +1197,8 @@ as \fBsudo\fR). Environment variables to be preserved in the user's environment when the \fIenv_reset\fR option is in effect. This allows fine-grained control over the environment \fBsudo\fR\-spawned processes will receive. -The argument may be a double\-quoted, space-separated list or a -single value without double\-quotes. The list can be replaced, added +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 variables to keep is displayed when \fBsudo\fR is run by root with the \fI\-V\fR option. @@ -1112,7 +1212,8 @@ supported: \fBalert\fR, \fBcrit\fR, \fBdebug\fR, \fBemerg\fR, \fBerr\fR, \fBinfo \&\fBnotice\fR, and \fBwarning\fR. .SH "FILES" .IX Header "FILES" -.IP "\fI@sysconfdir@/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 .IP "\fI/etc/group\fR" 24 @@ -1123,13 +1224,6 @@ Local groups file List of network groups .SH "EXAMPLES" .IX Header "EXAMPLES" -Since the \fIsudoers\fR file is parsed in a single pass, order is -important. In general, you should structure \fIsudoers\fR such that -the \f(CW\*(C`Host_Alias\*(C'\fR, \f(CW\*(C`User_Alias\*(C'\fR, and \f(CW\*(C`Cmnd_Alias\*(C'\fR specifications -come first, followed by any \f(CW\*(C`Default_Entry\*(C'\fR lines, and finally the -\&\f(CW\*(C`Runas_Alias\*(C'\fR and user specifications. The basic rule of thumb -is you cannot reference an Alias that has not already been defined. -.PP Below are example \fIsudoers\fR entries. Admittedly, some of these are a bit contrived. First, we define our \fIaliases\fR: .PP @@ -1138,15 +1232,11 @@ these are a bit contrived. First, we define our \fIaliases\fR: \& User_Alias FULLTIMERS = millert, mikef, dowdy \& User_Alias PARTTIMERS = bostley, jwfox, crawl \& User_Alias WEBMASTERS = will, wendy, wim -.Ve -.PP -.Vb 3 +\& \& # Runas alias specification \& Runas_Alias OP = root, operator \& Runas_Alias DB = oracle, sybase -.Ve -.PP -.Vb 9 +\& \& # Host alias specification \& Host_Alias SPARC = bigtime, eclipse, moet, anchor :\e \& SGI = grolsch, dandelion, black :\e @@ -1156,9 +1246,7 @@ these are a bit contrived. First, we define our \fIaliases\fR: \& Host_Alias CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0 \& Host_Alias SERVERS = master, mail, www, ns \& Host_Alias CDROM = orion, perseus, hercules -.Ve -.PP -.Vb 13 +\& \& # Cmnd alias specification \& Cmnd_Alias DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\e \& /usr/sbin/restore, /usr/sbin/rrestore @@ -1187,7 +1275,7 @@ disable shell escapes for the commands in the \s-1PAGERS\s0 \f(CW\*(C`Cmnd_Alias (\fI/usr/bin/more\fR, \fI/usr/bin/pg\fR and \fI/usr/bin/less\fR). .PP .Vb 7 -\& # Override built-in defaults +\& # Override built\-in defaults \& Defaults syslog=auth \& Defaults>root !set_logname \& Defaults:FULLTIMERS !lecture @@ -1257,7 +1345,7 @@ directory \fI/usr/oper/bin/\fR. The user \fBjoe\fR may only \fIsu\fR\|(1) to operator. .PP .Vb 1 -\& pete HPPA = /usr/bin/passwd [A-z]*, !/usr/bin/passwd root +\& pete HPPA = /usr/bin/passwd [A\-Za\-z]*, !/usr/bin/passwd root .Ve .PP The user \fBpete\fR is allowed to change anyone's password except for @@ -1294,11 +1382,11 @@ The user \fBfred\fR can run commands as any user in the \fI\s-1DB\s0\fR \f(CW\*( (\fBoracle\fR or \fBsybase\fR) without giving a password. .PP .Vb 1 -\& john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root* +\& john ALPHA = /usr/bin/su [!\-]*, !/usr/bin/su *root* .Ve .PP On the \fI\s-1ALPHA\s0\fR machines, user \fBjohn\fR may su to anyone except root -but he is not allowed to give \fIsu\fR\|(1) any flags. +but he is not allowed to specify any options to the \fIsu\fR\|(1) command. .PP .Vb 1 \& jen ALL, !SERVERS = ALL @@ -1339,7 +1427,7 @@ web pages) or simply \fIsu\fR\|(1) to www. .PP .Vb 2 \& ALL CDROM = NOPASSWD: /sbin/umount /CDROM,\e -\& /sbin/mount -o nosuid\e,nodev /dev/cd0a /CDROM +\& /sbin/mount \-o nosuid\e,nodev /dev/cd0a /CDROM .Ve .PP Any user may mount or unmount a CD-ROM on the machines in the \s-1CDROM\s0 @@ -1395,7 +1483,7 @@ To tell whether or not \fBsudo\fR supports \fInoexec\fR, you can run the following as root: .Sp .Vb 1 -\& sudo -V | grep "dummy exec" +\& sudo \-V | grep "dummy exec" .Ve .Sp If the resulting output contains a line that begins with: @@ -1407,7 +1495,7 @@ If the resulting output contains a line that begins with: then \fBsudo\fR may be able to replace the exec family of functions in the standard library with its own that simply return an error. Unfortunately, there is no foolproof way to know whether or not -\&\fInoexec\fR will work at compile\-time. \fInoexec\fR should work on +\&\fInoexec\fR will work at compile-time. \fInoexec\fR should work on SunOS, Solaris, *BSD, Linux, \s-1IRIX\s0, Tru64 \s-1UNIX\s0, MacOS X, and HP-UX 11.x. It is known \fBnot\fR to work on \s-1AIX\s0 and UnixWare. \fInoexec\fR is expected to work on most operating systems that support the diff --git a/sudoers.pod b/sudoers.pod index f65db6b..63c49cf 100644 --- a/sudoers.pod +++ b/sudoers.pod @@ -1,4 +1,4 @@ -Copyright (c) 1994-1996, 1998-2005, 2007 +Copyright (c) 1994-1996, 1998-2005, 2007-2008 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.95.2.26 2008/02/19 18:13:17 millert Exp $ +$Sudo: sudoers.pod,v 1.155 2008/12/03 20:57:13 millert Exp $ =pod =head1 NAME @@ -113,32 +113,32 @@ The definitions of what constitutes a valid I member follow. User ',' User_List User ::= '!'* username | + '!'* '#'uid | '!'* '%'group | '!'* '+'netgroup | '!'* User_Alias -A C is made up of one or more usernames, system groups -(prefixed with '%'), netgroups (prefixed with '+') and other aliases. -Each list item may be prefixed with one or more '!' operators. -An odd number of '!' operators negate the value of the item; an even -number just cancel each other out. - - Runas_List ::= Runas_User | - Runas_User ',' Runas_List - - Runas_User ::= '!'* username | - '!'* '#'uid | - '!'* '%'group | - '!'* +netgroup | - '!'* Runas_Alias - -A C is similar to a C except that it can -also contain uids (prefixed with '#') and instead of Ces -it can contain Ces. Note that usernames and groups -are matched as strings. In other words, two users (groups) with -the same uid (gid) are considered to be distinct. If you wish to -match all usernames with the same uid (e.g.Eroot and toor), you -can use a uid instead (#0 in the example given). +A C is made up of one or more usernames, uids (prefixed +with '#'), system groups (prefixed with '%'), netgroups (prefixed +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. + + Runas_List ::= Runas_Member | + Runas_Member ',' Runas_List + + Runas_Member ::= '!'* username | + '!'* '#'uid | + '!'* '%'group | + '!'* +netgroup | + '!'* Runas_Alias + +A C is similar to a C except that instead +of Ces it can contain Ces. Note that +usernames and groups are matched as strings. In other words, two +users (groups) with the same uid (gid) are considered to be distinct. +If you wish to match all usernames with the same uid (e.g.Eroot +and toor), you can use a uid instead (#0 in the example given). Host_List ::= Host | Host ',' Host_List @@ -192,7 +192,7 @@ in the C must match exactly those given by the user on the command line (or match the wildcards if there are any). Note that the following characters must be escaped with a '\' if they are used in command arguments: ',', ':', '=', '\'. The special command C<"sudoedit"> -is used to permit a user to run B with the B<-e> flag (or +is used to permit a user to run B with the B<-e> option (or as B). It may take command line arguments just as a normal command does. @@ -201,11 +201,15 @@ a normal command does. Certain configuration options may be changed from their default values at runtime via one or more C lines. These may affect all users on any host, all users on a specific host, a -specific user, or commands being run as a specific user. +specific user, a specific command, or commands being run as a specific user. +Note that per-command entries may not include command line arguments. +If you need to specify arguments, define a C and reference +that instead. Default_Type ::= 'Defaults' | 'Defaults' '@' Host_List | 'Defaults' ':' User_List | + 'Defaults' '!' Cmnd_List | 'Defaults' '>' Runas_List Default_Entry ::= Default_Type Parameter_List @@ -230,6 +234,10 @@ These operators are used to add to and delete from a list respectively. It is not an error to use the C<-=> operator to remove an element that does 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 L for a list of supported Defaults parameters. =head2 User Specification @@ -242,10 +250,10 @@ See L for a list of supported Defaults parameters. Cmnd_Spec ::= Runas_Spec? Tag_Spec* Cmnd - Runas_Spec ::= '(' Runas_List ')' + Runas_Spec ::= '(' Runas_List? (: Runas_List)? ')' Tag_Spec ::= ('NOPASSWD:' | 'PASSWD:' | 'NOEXEC:' | 'EXEC:' | - 'SETENV:' | 'NOSETENV:') + 'SETENV:' | 'NOSETENV:' ) A B determines which commands a user may run (and as what user) on specified hosts. By default, commands are @@ -255,11 +263,24 @@ Let's break that down into its constituent parts: =head2 Runas_Spec -A C is simply a C (as defined above) -enclosed in a set of parentheses. If you do not specify a -C in the user specification, a default C -of B will be used. A C sets the default for -commands that follow it. What this means is that for the entry: +A C determines the user and/or the group that a command +may be run as. A fully-specified C consists of two +Cs (as defined above) separated by a colon (':') and +enclosed in a set of parentheses. The first C indicates +which users the command may be run as via B's B<-u> option. +The second defines a list of groups that can be specified via +B's B<-g> option. If both Cs are specified, the +command may be run with any combination of users and groups listed +in their respective Cs. If only the first is specified, +the command may be run as any user in the list but no B<-g> option +may be specified. If the first C is empty but the +second is specified, the command may be run as the invoking user +with the group set to any listed in the C. If no +C is specified the command may be run as B and +no group may be specified. + +A C sets the default for the commands that follow it. +What this means is that for the entry: dgb boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm @@ -276,10 +297,23 @@ entry. If we modify the entry like so: Then user B is now allowed to run F as B, but F and F as B. +We can extend this to allow B to run C with either +the user or group set to B: + + dgb boulder = (operator : operator) /bin/ls, (root) /bin/kill, \ + /usr/bin/lprm + +In the following example, user B may run commands that access +a modem device file with the dialer group. Note that in this example +only the group will be set, the command still runs as user B. + + tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu, \ + /usr/local/bin/minicom + =head2 Tag_Spec A command may have zero or more tags associated with it. There are -six possible tag values, C, C, C, C, +eight possible tag values, C, C, C, C, C and C. Once a tag is set on a C, subsequent Cs in the C, inherit the tag unless it is overridden by the @@ -298,7 +332,7 @@ For example: ray rushmore = NOPASSWD: /bin/kill, /bin/ls, /usr/bin/lprm would allow the user B to run F, F, and -F as root on the machine rushmore as B without +F as B on the machine rushmore without authenticating himself. If we only want B to be able to run F without a password the entry would be: @@ -342,7 +376,7 @@ be overridden by use of the C tag. =head2 Wildcards B allows shell-style I (aka meta or glob characters) -to be used in pathnames as well as command line arguments in the +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. @@ -371,6 +405,15 @@ 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: + + /bin/ls [[\:alpha\:]]* + +Would match any filename beginning with a letter. + Note that a forward slash ('/') will B be matched by wildcards used in the pathname. When matching the command line arguments, however, a slash B get matched by @@ -394,6 +437,26 @@ with B arguments. =back +=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: + + #include /etc/sudoers.local + +When B reaches this line it will suspend processing of the +current file (F) and switch to F. +Upon reaching the end of F, the rest of +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. + =head2 Other special characters and reserved words The pound sign ('#') is used to indicate a comment (unless it is @@ -441,7 +504,7 @@ B: If set, B will set the C environment variable to the home directory of the target user (which is root unless the B<-u> option is used). -This effectively means that the B<-H> flag is always implied. +This effectively means that the B<-H> option is always implied. This flag is I by default. =item authenticate @@ -451,6 +514,12 @@ means of authentication) before they may run commands. This default may be overridden via the C and C tags. This flag is I by default. +=item closefrom_override + +If set, the user may use B's B<-C> option which +overrides the default starting point at which B begins +closing open file descriptors. This flag is I by default. + =item env_editor If set, B will use the value of the EDITOR or VISUAL @@ -469,9 +538,9 @@ LOGNAME, SHELL, USER, USERNAME and the C variables. Any variables in the caller's environment that match the C and C lists are then added. The default contents of the C and C lists are displayed when B is -run by root with the I<-V> option. If B was compiled with -the C option, its value will be used for the C -environment variable. This flag is I by default. +run by root with the I<-V> option. If the I option +is set, its value will be used for the C environment variable. +This flag is I by default. =item fqdn @@ -492,10 +561,7 @@ I. This flag is I<@fqdn@> by default. If set, B will ignore '.' or '' (current dir) in the C environment variable; the C itself is not modified. This -flag is I<@ignore_dot@> by default. Currently, while it is possible -to set I in I, its value is not used. This option -should be considered read-only (it will be fixed in a future version -of B). +flag is I<@ignore_dot@> by default. =item ignore_local_sudoers @@ -596,11 +662,9 @@ user. This flag is I by default. =item requiretty If set, B will only run when the user is logged in to a real -tty. This will disallow things like C<"rsh somehost sudo ls"> since -L does not allocate a tty. Because it is not possible to turn -off echo when there is no tty present, some sites may wish to set -this flag to prevent a user from entering a visible password. This -flag is I by default. +tty. When this flag is set, B can only be run from a login +session and not via other means such as L or cgi-bin scripts. +This flag is I by default. =item root_sudo @@ -625,16 +689,16 @@ password of the invoking user. This flag is I by default. =item set_home -If set and B is invoked with the B<-s> flag the C +If set and B is invoked with the B<-s> option the C environment variable will be set to the home directory of the target user (which is root unless the B<-u> option is used). This effectively -makes the B<-s> flag imply B<-H>. This flag is I by default. +makes the B<-s> option imply B<-H>. This flag is I by default. =item set_logname Normally, B will set the C, C and C environment variables to the name of the target user (usually root -unless the B<-u> flag is given). However, since some programs +unless the B<-u> option is given). However, since some programs (including the RCS revision control system) use C to determine the real identity of the user, it may be desirable to change this behavior. This can be done by negating the set_logname @@ -654,7 +718,7 @@ by default. =item shell_noargs If set and B is invoked with no arguments it acts as if the -B<-s> flag had been given. That is, it runs a shell as root (the +B<-s> option had been given. That is, it runs a shell as root (the 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. @@ -673,9 +737,9 @@ function. This flag is I by default. =item targetpw If set, B will prompt for the password of the user specified by -the B<-u> flag (defaults to C) instead of the password of the +the B<-u> option (defaults to C) 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 B<-u> flag. +in the passwd database as an argument to the B<-u> option. This flag is I by default. =item tty_tickets @@ -692,12 +756,29 @@ If set, B will apply the defaults specified for the target user's login class if one exists. Only available if B is configured with the --with-logincap option. This flag is I by default. +=item visiblepw + +By default, B will refuse to run if the user must enter a +password but it is not possible to disable echo on the terminal. +If the I flag is set, B will prompt for a password +even when it would be visible on the screen. This makes it possible +to run things like C<"rsh somehost sudo ls"> since L does +not allocate a tty. This flag is I by default. + =back B: =over 16 +=item closefrom + +Before it executes a command, B will close all open file +descriptors other than standard input, standard output and standard +error (ie: file descriptors 0-2). The I option can be used +to specify a different file descriptor at which to start closing. +The default is C<3>. + =item passwd_tries The number of tries a user gets to enter his/her password before @@ -733,7 +814,12 @@ own timestamps via C and C respectively. =item umask Umask to use when running the command. Negate this option or set -it to 0777 to preserve the user's umask. The default is C<@sudo_umask@>. +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 C<@sudo_umask@>. +This guarantees that B never 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 in +I. =back @@ -816,7 +902,7 @@ This option is only available whe B is built with SELinux support. =item runas_default -The default user to run commands as if the B<-u> flag is not specified +The default user to run commands as if the B<-u> option is not specified on the command line. This defaults to C<@runas_default@>. Note that if I is set it B occur before any C specifications. @@ -831,6 +917,12 @@ Defaults to C<@badpri@>. Syslog priority to use when user authenticates successfully. Defaults to C<@goodpri@>. +=item sudoers_locale + +Locale to use when parsing the sudoers file. Note that changing +the locale may affect how sudoers is interpreted. +Defaults to C<"C">. + =item timestampdir The directory in which B stores its timestamp files. @@ -854,6 +946,25 @@ B: =over 12 +=item askpass + +The I option specifies the fully qualified path to a helper +program used to read the user's password when no terminal is +available. This may be the case when B is executed from a +graphical (as opposed to text-based) application. The program +specified by I should display the argument passed to it +as the prompt and write the user's password to the standard output. +The value of I may be overridden by the C +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. + =item exempt_group Users in this group are exempt from password and PATH requirements. @@ -893,7 +1004,7 @@ By default, B uses a built-in lecture. =item listpw This option controls when a password will be required when a -user runs B with the B<-l> flag. It has the following possible values: +user runs B with the B<-l> option. It has the following possible values: =over 8 @@ -904,7 +1015,7 @@ the C flag set to avoid entering a password. =item always -The user must always enter a password to use the B<-l> flag. +The user must always enter a password to use the B<-l> option. =item any @@ -913,7 +1024,7 @@ must have the C flag set to avoid entering a password. =item never -The user need never enter a password to use the B<-l> flag. +The user need never enter a password to use the B<-l> option. =back @@ -936,12 +1047,28 @@ Flags to use when invoking mailer. Defaults to B<-t>. Path to mail program used to send warning mail. Defaults to the path to sendmail found at configure time. +=item mailfrom + +Address to use for the "from" address when sending warning and error +mail. The address should be enclosed in double quotes (C<">) to +protect against B interpreting the C<@> sign. Defaults to +the name of the user running B. + =item mailto Address to send warning and error mail to. The address should be enclosed in double quotes (C<">) to protect against B interpreting the C<@> sign. Defaults to C<@mailto@>. +=item secure_path + +Path used for every command run from B. If you don't trust the +people running B to have a sane C 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 +I option are not affected by I. +This is not set by default. + =item syslog Syslog facility if syslog is being used for logging (negate to @@ -950,7 +1077,7 @@ disable syslog logging). Defaults to C<@logfac@>. =item verifypw This option controls when a password will be required when a user runs -B with the B<-v> flag. It has the following possible values: +B with the B<-v> option. It has the following possible values: =over 8 @@ -961,7 +1088,7 @@ the C flag set to avoid entering a password. =item always -The user must always enter a password to use the B<-v> flag. +The user must always enter a password to use the B<-v> option. =item any @@ -970,7 +1097,7 @@ must have the C flag set to avoid entering a password. =item never -The user need never enter a password to use the B<-v> flag. +The user need never enter a password to use the B<-v> option. =back @@ -1052,13 +1179,6 @@ List of network groups =head1 EXAMPLES -Since the I file is parsed in a single pass, order is -important. In general, you should structure I such that -the C, C, and C specifications -come first, followed by any C lines, and finally the -C and user specifications. The basic rule of thumb -is you cannot reference an Alias that has not already been defined. - Below are example I entries. Admittedly, some of these are a bit contrived. First, we define our I: @@ -1161,7 +1281,7 @@ directory F. The user B may only L to operator. - pete HPPA = /usr/bin/passwd [A-z]*, !/usr/bin/passwd root + pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root The user B is allowed to change anyone's password except for root on the I machines. Note that this assumes L @@ -1191,7 +1311,7 @@ The user B can run commands as any user in the I C john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root* On the I machines, user B may su to anyone except root -but he is not allowed to give L any flags. +but he is not allowed to specify any options to the L command. jen ALL, !SERVERS = ALL diff --git a/sudoers2ldif b/sudoers2ldif index da5bb97..df51b9f 100644 --- a/sudoers2ldif +++ b/sudoers2ldif @@ -5,7 +5,7 @@ use strict; # Converts a sudoers file to LDIF format in prepration for loading into # the LDAP server. # -# $Sudo: sudoers2ldif,v 1.2.2.1 2007/06/28 14:45:19 millert Exp $ +# $Sudo: sudoers2ldif,v 1.5 2007/12/08 00:09:28 millert Exp $ # # BUGS: @@ -14,9 +14,12 @@ use strict; # Does not yet escape + at the beginning of a dn # Does not yet handle line wraps correctly # Does not yet handle multiple roles with same name (needs tiebreaker) -# Sudoers entries can have multiple Runas entries that override former ones, -# with LDAP sudoRunas applies to all commands in a sudoRole +# +# CAVEATS: +# Sudoers entries can have multiple RunAs entries that override former ones, +# with LDAP sudoRunAs{Group,User} applies to all commands in a sudoRole +my %RA; my %UA; my %HA; my %CA; @@ -51,8 +54,10 @@ while (<>){ $p2=~s/\s+$//; # remove trailing whitespace $p3=~s/\s+$//; # remove trailing whitespace - if ($p1 eq "User_Alias") { + if ($p1 eq "User_Alias") { $UA{$p2}=$p3; + } elsif ($p1 eq "Runas_Alias") { + $RA{$p2}=$p3; } elsif ($p1 eq "Host_Alias") { $HA{$p2}=$p3; } elsif ($p1 eq "Cmnd_Alias") { @@ -80,10 +85,15 @@ while (<>){ # will clobber options print "sudoUser: $_\n" foreach expand(\%UA,@users); print "sudoHost: $_\n" foreach expand(\%HA,@hosts); - my $runas = undef; foreach (@cmds) { if (s/^\(([^\)]+)\)\s*//) { - print "sudoRunas: $_\n" foreach expand(\%UA, split(/,\s*/, $1)); + my @runas = split(/:\s*/, $1); + if (defined($runas[0])) { + print "sudoRunAsUser: $_\n" foreach expand(\%RA, split(/,\s*/, $runas[0])); + } + if (defined($runas[1])) { + print "sudoRunAsGroup: $_\n" foreach expand(\%RA, split(/,\s*/, $runas[1])); + } } } print "sudoCommand: $_\n" foreach expand(\%CA,@cmds); diff --git a/testsudoers.c b/testsudoers.c index 3b213f3..0eaf1d7 100644 --- a/testsudoers.c +++ b/testsudoers.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1996, 1998-2005 Todd C. Miller + * Copyright (c) 1996, 1998-2005, 2007-2008 + * 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,394 +54,330 @@ #ifdef HAVE_NETGROUP_H # include #endif /* HAVE_NETGROUP_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #include #include #include #include #include -#include #include "sudo.h" -#include "parse.h" #include "interfaces.h" +#include "parse.h" +#include #ifndef HAVE_FNMATCH # include "emul/fnmatch.h" #endif /* HAVE_FNMATCH */ #ifndef lint -__unused static const char rcsid[] = "$Sudo: testsudoers.c,v 1.88.2.7 2008/02/09 14:44:49 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: testsudoers.c,v 1.128 2008/11/19 17:01:20 millert Exp $"; #endif /* lint */ -/* - * Prototypes - */ -void init_parser __P((void)); -void dumpaliases __P((void)); - /* * Globals */ int Argc, NewArgc; char **Argv, **NewArgv; -int parse_error = FALSE; int num_interfaces; struct interface *interfaces; struct sudo_user sudo_user; -extern int clearaliases; -extern int pedantic; - -/* - * Returns TRUE if "s" has shell meta characters in it, - * else returns FALSE. - */ -int -has_meta(s) - char *s; -{ - char *t; +struct passwd *list_pw; +extern int parse_error; + +/* passwd/group redirection for pwutil.c */ +void (*my_setgrent) __P((void)) = setgrent; +void (*my_endgrent) __P((void)) = endgrent; +struct group *(*my_getgrnam) __P((const char *)) = getgrnam; +struct group *(*my_getgrgid) __P((gid_t)) = getgrgid; +void (*my_setpwent) __P((void)) = setpwent; +void (*my_endpwent) __P((void)) = endpwent; +struct passwd *(*my_getpwnam) __P((const char *)) = getpwnam; +struct passwd *(*my_getpwuid) __P((uid_t)) = getpwuid; + +/* For getopt(3) */ +extern char *optarg; +extern int optind; + +#if defined(SUDO_DEVEL) && defined(__OpenBSD__) +extern char *malloc_options; +#endif +#ifdef YYDEBUG +extern int yydebug; +#endif - for (t = s; *t; t++) { - if (*t == '\\' || *t == '?' || *t == '*' || *t == '[' || *t == ']') - return(TRUE); - } - return(FALSE); -} +int print_alias __P((void *, void *)); +void dump_sudoers __P((void)); +void print_defaults __P((void)); +void print_privilege __P((struct privilege *)); +void print_userspecs __P((void)); +void usage __P((void)) __attribute__((__noreturn__)); +void set_runasgr __P((char *)); +void set_runaspw __P((char *)); + +extern void ts_setgrfile __P((const char *)); +extern void ts_setgrent __P((void)); +extern void ts_endgrent __P((void)); +extern struct group *ts_getgrent __P((void)); +extern struct group *ts_getgrnam __P((const char *)); +extern struct group *ts_getgrgid __P((gid_t)); +extern void ts_setpwfile __P((const char *)); +extern void ts_setpwent __P((void)); +extern void ts_endpwent __P((void)); +extern struct passwd *ts_getpwent __P((void)); +extern struct passwd *ts_getpwnam __P((const char *)); +extern struct passwd *ts_getpwuid __P((uid_t)); -/* - * Returns TRUE if user_cmnd matches, in the sudo sense, - * the pathname in path; otherwise, return FALSE - */ int -command_matches(path, sudoers_args) - char *path; - char *sudoers_args; +main(argc, argv) + int argc; + char **argv; { - int clen, plen; - char *args; - - if (user_cmnd == NULL) - return(FALSE); - - if ((args = strchr(path, ' '))) - *args++ = '\0'; - - if (has_meta(path)) { - if (fnmatch(path, user_cmnd, FNM_PATHNAME)) - return(FALSE); - if (!sudoers_args) - return(TRUE); - else if (!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) - return(TRUE); - else if (sudoers_args) - return((fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)); - else - return(FALSE); - } else { - plen = strlen(path); - if (path[plen - 1] != '/') { - if (strcmp(user_cmnd, path)) - return(FALSE); - if (!sudoers_args) - return(TRUE); - else if (!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) - return(TRUE); - else if (sudoers_args) - return((fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)); - else - return(FALSE); - } + struct cmndspec *cs; + struct privilege *priv; + struct userspec *us; + char *p, *grfile, *pwfile, *runas_group, *runas_user; + char hbuf[MAXHOSTNAMELEN + 1]; + int ch, dflag, rval, matched; + +#if defined(SUDO_DEVEL) && defined(__OpenBSD__) + malloc_options = "AFGJPR"; +#endif +#ifdef YYDEBUG + yydebug = 1; +#endif - clen = strlen(user_cmnd); - if (clen < plen + 1) - /* path cannot be the parent dir of user_cmnd */ - return(FALSE); + Argv = argv; + Argc = argc; - if (strchr(user_cmnd + plen + 1, '/') != NULL) - /* path could only be an anscestor of user_cmnd -- */ - /* ignoring, of course, things like // & /./ */ - return(FALSE); + dflag = 0; + grfile = pwfile = runas_group = runas_user = NULL; + while ((ch = getopt(argc, argv, "dg:G:h:p:u:")) != -1) { + switch (ch) { + case 'd': + dflag = 1; + break; + case 'h': + user_host = optarg; + break; + case 'G': + grfile = optarg; + break; + case 'g': + runas_group = optarg; + break; + case 'p': + pwfile = optarg; + break; + case 'u': + runas_user = optarg; + break; + default: + usage(); + break; + } + } + argc -= optind; + argv += optind; + NewArgc = argc; + NewArgv = argv; + + /* Set group/passwd file and init the cache. */ + if (grfile) { + my_setgrent = ts_setgrent; + my_endgrent = ts_endgrent; + my_getgrnam = ts_getgrnam; + my_getgrgid = ts_getgrgid; + ts_setgrfile(grfile); + } + if (pwfile) { + my_setpwent = ts_setpwent; + my_endpwent = ts_endpwent; + my_getpwnam = ts_getpwnam; + my_getpwuid = ts_getpwuid; + ts_setpwfile(pwfile); + } + sudo_setpwent(); + sudo_setgrent(); + + if (argc < 2) { + if (!dflag) + usage(); + if ((sudo_user.pw = sudo_getpwnam("nobody")) == NULL) + errorx(1, "no passwd entry for nobody!"); + user_cmnd = user_base = "true"; + } else { + if ((sudo_user.pw = sudo_getpwnam(*argv)) == NULL) + errorx(1, "no passwd entry for %s!", *argv); + user_cmnd = *++argv; + if ((p = strrchr(user_cmnd, '/')) != NULL) + user_base = p + 1; + else + user_base = user_cmnd; + NewArgc -= 2; + } - /* see whether path is the prefix of user_cmnd */ - return((strncmp(user_cmnd, path, plen) == 0)); + if (user_host == NULL) { + if (gethostname(hbuf, sizeof(hbuf)) != 0) + error(1, "gethostname"); + hbuf[sizeof(hbuf) - 1] = '\0'; + user_host = hbuf; + } + if ((p = strchr(user_host, '.'))) { + *p = '\0'; + user_shost = estrdup(user_host); + *p = '.'; + } else { + user_shost = user_host; } -} -static int -addr_matches_if(n) - char *n; -{ - int i; - struct in_addr addr; - struct interface *ifp; -#ifdef HAVE_IN6_ADDR - struct in6_addr addr6; - int j; -#endif - int family; + /* Fill in user_args from NewArgv. */ + if (NewArgc > 1) { + char *to, **from; + size_t size, n; -#ifdef HAVE_IN6_ADDR - if (inet_pton(AF_INET6, n, &addr6) > 0) { - family = AF_INET6; - } else -#endif - { - family = AF_INET; - addr.s_addr = inet_addr(n); - } + for (size = 0, from = NewArgv + 1; *from; from++) + size += strlen(*from) + 1; - for (i = 0; i < num_interfaces; i++) { - ifp = &interfaces[i]; - if (ifp->family != family) - continue; - switch(family) { - case AF_INET: - if (ifp->addr.ip4.s_addr == addr.s_addr || - (ifp->addr.ip4.s_addr & ifp->netmask.ip4.s_addr) - == addr.s_addr) - return(TRUE); - break; -#ifdef HAVE_IN6_ADDR - case AF_INET6: - if (memcmp(ifp->addr.ip6.s6_addr, addr6.s6_addr, - sizeof(addr6.s6_addr)) == 0) - return(TRUE); - for (j = 0; j < sizeof(addr6.s6_addr); j++) { - if ((ifp->addr.ip6.s6_addr[j] & ifp->netmask.ip6.s6_addr[j]) != addr6.s6_addr[j]) - break; - } - if (j == sizeof(addr6.s6_addr)) - return(TRUE); -#endif /* HAVE_IN6_ADDR */ + user_args = (char *) emalloc(size); + for (to = user_args, from = NewArgv + 1; *from; from++) { + n = strlcpy(to, *from, size - (to - user_args)); + if (n >= size - (to - user_args)) + errorx(1, "internal error, init_vars() overflow"); + to += n; + *to++ = ' '; } + *--to = '\0'; } - return(FALSE); -} + /* Initialize default values. */ + init_defaults(); -static int -addr_matches_if_netmask(n, m) - char *n; - char *m; -{ - int i; - struct in_addr addr, mask; - struct interface *ifp; -#ifdef HAVE_IN6_ADDR - struct in6_addr addr6, mask6; - int j; -#endif - int family; + /* Load ip addr/mask for each interface. */ + load_interfaces(); -#ifdef HAVE_IN6_ADDR - if (inet_pton(AF_INET6, n, &addr6) > 0) - family = AF_INET6; + /* Allocate space for data structures in the parser. */ + init_parser("sudoers", 0); + + if (yyparse() != 0 || parse_error) + (void) fputs("Does not parse", stdout); else -#endif - { - family = AF_INET; - addr.s_addr = inet_addr(n); - } + (void) fputs("Parses OK", stdout); - if (family == AF_INET) { - if (strchr(m, '.')) - mask.s_addr = inet_addr(m); - else { - i = 32 - atoi(m); - mask.s_addr = 0xffffffff; - mask.s_addr >>= i; - mask.s_addr <<= i; - mask.s_addr = htonl(mask.s_addr); - } - } -#ifdef HAVE_IN6_ADDR - else { - if (inet_pton(AF_INET6, m, &mask6) <= 0) { - j = atoi(m); - for (i = 0; i < 16; i++) { - if (j < i * 8) - mask6.s6_addr[i] = 0; - else if (i * 8 + 8 <= j) - mask6.s6_addr[i] = 0xff; - else - mask6.s6_addr[i] = 0xff00 >> (j - i * 8); - } - } + if (!update_defaults(SETDEF_ALL)) + (void) fputs(" (problem with defaults entries)", stdout); + puts("."); + + /* + * Set runas passwd/group entries based on command line or sudoers. + * Note that if runas_group was specified without runas_user we + * defer setting runas_pw so the match routines know to ignore it. + */ + if (runas_group != NULL) { + set_runasgr(runas_group); + if (runas_user != NULL) + set_runaspw(runas_user); + } else + set_runaspw(runas_user ? runas_user : def_runas_default); + + if (dflag) { + (void) putchar('\n'); + dump_sudoers(); + if (argc < 2) + exit(0); } -#endif /* HAVE_IN6_ADDR */ - for (i = 0; i < num_interfaces; i++) { - ifp = &interfaces[i]; - if (ifp->family != family) + /* This loop must match the one in sudoers_lookup() */ + printf("\nEntries for user %s:\n", user_name); + matched = UNSPEC; + tq_foreach_rev(&userspecs, us) { + if (userlist_matches(sudo_user.pw, &us->users) != ALLOW) continue; - switch(family) { - case AF_INET: - if ((ifp->addr.ip4.s_addr & mask.s_addr) == addr.s_addr) - return(TRUE); -#ifdef HAVE_IN6_ADDR - case AF_INET6: - for (j = 0; j < sizeof(addr6.s6_addr); j++) { - if ((ifp->addr.ip6.s6_addr[j] & mask6.s6_addr[j]) != addr6.s6_addr[j]) - break; + tq_foreach_rev(&us->privileges, priv) { + putchar('\n'); + print_privilege(priv); /* XXX */ + putchar('\n'); + if (hostlist_matches(&priv->hostlist) == ALLOW) { + puts("\thost matched"); + tq_foreach_rev(&priv->cmndlist, cs) { + if (runaslist_matches(&cs->runasuserlist, + &cs->runasgrouplist) == ALLOW) { + puts("\trunas matched"); + rval = cmnd_matches(cs->cmnd); + if (rval != UNSPEC) + matched = rval; + printf("\tcmnd %s\n", rval == ALLOW ? "allowed" : + rval == DENY ? "denied" : "unmatched"); + } } - if (j == sizeof(addr6.s6_addr)) - return(TRUE); -#endif /* HAVE_IN6_ADDR */ + } else + puts("\thost unmatched"); } } + printf("\nCommand %s\n", matched == ALLOW ? "allowed" : + matched == DENY ? "denied" : "unmatched"); - return(FALSE); -} - -/* - * Returns TRUE if "n" is one of our ip addresses or if - * "n" is a network that we are on, else returns FALSE. - */ -int -addr_matches(n) - char *n; -{ - char *m; - int retval; - - /* If there's an explicit netmask, use it. */ - if ((m = strchr(n, '/'))) { - *m++ = '\0'; - retval = addr_matches_if_netmask(n, m); - *(m - 1) = '/'; - } else - retval = addr_matches_if(n); - - return(retval); -} - -int -hostname_matches(shost, lhost, pattern) - char *shost; - char *lhost; - char *pattern; -{ - if (has_meta(pattern)) { - if (strchr(pattern, '.')) - return(fnmatch(pattern, lhost, FNM_CASEFOLD)); - else - return(fnmatch(pattern, shost, FNM_CASEFOLD)); - } else { - if (strchr(pattern, '.')) - return(strcasecmp(lhost, pattern)); - else - return(strcasecmp(shost, pattern)); - } + exit(0); } -int -userpw_matches(sudoers_user, user, pw) - char *sudoers_user; +void +set_runaspw(user) char *user; - struct passwd *pw; { - if (pw != NULL && *sudoers_user == '#') { - uid_t uid = atoi(sudoers_user + 1); - if (uid == pw->pw_uid) - return(1); + if (*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) + errorx(1, "unknown user: %s", user); } - return(strcmp(sudoers_user, user) == 0); } -int -usergr_matches(group, user, pw) +void +set_runasgr(group) char *group; - char *user; - struct passwd *pw; { - struct group *grp; - char **cur; - - /* Make sure we have a valid usergroup, sudo style. */ - if (*group++ != '%') - return(FALSE); - - if ((grp = getgrnam(group)) == NULL) - return(FALSE); - - /* - * Check against user's real gid as well as group's user list - */ - if (getgid() == grp->gr_gid) - return(TRUE); - - for (cur=grp->gr_mem; *cur; cur++) { - if (strcmp(*cur, user) == 0) - return(TRUE); + if (*group == '#') { + if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL) + runas_gr = sudo_fakegrnam(group); + } else { + if ((runas_gr = sudo_getgrnam(group)) == NULL) + errorx(1, "unknown group: %s", group); } - - return(FALSE); } -int -netgr_matches(netgr, host, shost, user) - char *netgr; - char *host; - char *shost; - char *user; +void +sudo_setspent() { -#ifdef HAVE_GETDOMAINNAME - static char *domain = (char *) -1; -#else - static char *domain = NULL; -#endif /* HAVE_GETDOMAINNAME */ - - /* Make sure we have a valid netgroup, sudo style. */ - if (*netgr++ != '+') - return(FALSE); - -#ifdef HAVE_GETDOMAINNAME - /* Get the domain name (if any). */ - if (domain == (char *) -1) { - domain = (char *) emalloc(MAXHOSTNAMELEN); - - if (getdomainname(domain, MAXHOSTNAMELEN) != 0 || *domain == '\0') { - efree(domain); - domain = NULL; - } - } -#endif /* HAVE_GETDOMAINNAME */ - -#ifdef HAVE_INNETGR - if (innetgr(netgr, host, user, domain)) - return(TRUE); - else if (host != shost && innetgr(netgr, shost, user, domain)) - return(TRUE); -#endif /* HAVE_INNETGR */ - - return(FALSE); + return; } void -set_perms(i) - int i; +sudo_endspent() { return; } +char * +sudo_getepw(pw) + const struct passwd *pw; +{ + return (pw->pw_passwd); +} + void set_fqdn() { return; } -int -set_runaspw(user) - char *user; +FILE * +open_sudoers(path, keepopen) + const char *path; + int *keepopen; { - return(TRUE); + return(fopen(path, "r")); } void @@ -449,110 +386,194 @@ init_envtables() return; } -int -main(argc, argv) - int argc; - char **argv; +void +set_perms(perm) + int perm; { - struct passwd pw; - char *p; -#ifdef YYDEBUG - extern int yydebug; - yydebug = 1; -#endif - - Argv = argv; - Argc = argc; + return; +} - if (Argc >= 6 && strcmp(Argv[1], "-u") == 0) { - user_runas = &Argv[2]; - pw.pw_name = Argv[3]; - user_host = Argv[4]; - user_cmnd = Argv[5]; - - NewArgv = &Argv[5]; - NewArgc = Argc - 5; - } else if (Argc >= 4) { - pw.pw_name = Argv[1]; - user_host = Argv[2]; - user_cmnd = Argv[3]; - - NewArgv = &Argv[3]; - NewArgc = Argc - 3; - } else { - (void) fprintf(stderr, - "usage: sudo [-u user] [args]\n"); - exit(1); +void +cleanup(gotsignal) + int gotsignal; +{ + if (!gotsignal) { + sudo_endpwent(); + sudo_endgrent(); } +} - sudo_user.pw = &pw; /* user_name needs to be defined */ - - if ((p = strchr(user_host, '.'))) { - *p = '\0'; - user_shost = estrdup(user_host); - *p = '.'; - } else { - user_shost = user_host; +void +print_member(m) + struct member *m; +{ + struct sudo_command *c; + + if (m->negated) + putchar('!'); + if (m->name == NULL) + fputs("ALL", stdout); + else if (m->type != COMMAND) + fputs(m->name, stdout); + else { + c = (struct sudo_command *) m->name; + printf("%s%s%s", c->cmnd, c->args ? " " : "", + c->args ? c->args : ""); } +} - /* Fill in user_args from NewArgv. */ - if (NewArgc > 1) { - char *to, **from; - size_t size, n; - - size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) + - strlen(NewArgv[NewArgc-1]) + 1; - user_args = (char *) emalloc(size); - for (to = user_args, from = NewArgv + 1; *from; from++) { - n = strlcpy(to, *from, size - (to - user_args)); - if (n >= size - (to - user_args)) - errx(1, "internal error, init_vars() overflow"); - to += n; - *to++ = ' '; +void +print_defaults() +{ + struct defaults *d; + struct member *m; + + tq_foreach_fwd(&defaults, d) { + (void) fputs("Defaults", stdout); + switch (d->type) { + case DEFAULTS_HOST: + putchar('@'); + break; + case DEFAULTS_USER: + putchar(':'); + break; + case DEFAULTS_RUNAS: + putchar('>'); + break; + case DEFAULTS_CMND: + putchar('!'); + break; } - *--to = '\0'; + tq_foreach_fwd(&d->binding, m) { + if (m != tq_first(&d->binding)) + putchar(','); + print_member(m); + } + printf("\t%s%s", d->op == FALSE ? "!" : "", d->var); + if (d->val != NULL) { + printf("%c%s", d->op == TRUE ? '=' : d->op, d->val); + } + putchar('\n'); } +} - /* Initialize default values. */ - init_defaults(); - - /* Warn about aliases that are used before being defined. */ - pedantic = TRUE; - - /* Need to keep aliases around for dumpaliases(). */ - clearaliases = FALSE; - - /* Load ip addr/mask for each interface. */ - load_interfaces(); +int +print_alias(v1, v2) + void *v1, *v2; +{ + struct alias *a = (struct alias *)v1; + struct member *m; + struct sudo_command *c; + + switch (a->type) { + case HOSTALIAS: + (void) printf("Host_Alias\t%s = ", a->name); + break; + case CMNDALIAS: + (void) printf("Cmnd_Alias\t%s = ", a->name); + break; + case USERALIAS: + (void) printf("User_Alias\t%s = ", a->name); + break; + case RUNASALIAS: + (void) printf("Runas_Alias\t%s = ", a->name); + break; + } + tq_foreach_fwd(&a->members, m) { + if (m != tq_first(&a->members)) + fputs(", ", stdout); + if (m->type == COMMAND) { + c = (struct sudo_command *) m->name; + printf("%s%s%s", c->cmnd, c->args ? " " : "", + c->args ? c->args : ""); + } else + fputs(m->name, stdout); + } + putchar('\n'); + return(0); +} - /* Allocate space for data structures in the parser. */ - init_parser(); +void +print_privilege(priv) + struct privilege *priv; +{ + struct cmndspec *cs; + struct member *m; + struct privilege *p; + struct cmndtag tags; + + for (p = priv; p != NULL; p = p->next) { + if (p != priv) + fputs(" : ", stdout); + tq_foreach_fwd(&p->hostlist, m) { + if (m != tq_first(&p->hostlist)) + fputs(", ", stdout); + print_member(m); + } + fputs(" = ", stdout); + tags.nopasswd = tags.noexec = UNSPEC; + tq_foreach_fwd(&p->cmndlist, cs) { + if (cs != tq_first(&p->cmndlist)) + fputs(", ", stdout); + /* XXX - runasgrouplist too */ + if (!tq_empty(&cs->runasuserlist)) { + fputs("(", stdout); + tq_foreach_fwd(&cs->runasuserlist, m) { + if (m != tq_first(&cs->runasuserlist)) + fputs(", ", stdout); + print_member(m); + } + fputs(") ", stdout); + } +#ifdef HAVE_SELINUX + if (cs->role) + printf("ROLE=%s ", cs->role); + if (cs->type) + printf("TYPE=%s ", cs->type); +#endif /* HAVE_SELINUX */ + if (cs->tags.nopasswd != UNSPEC && cs->tags.nopasswd != tags.nopasswd) + printf("%sPASSWD: ", cs->tags.nopasswd ? "NO" : ""); + if (cs->tags.noexec != UNSPEC && cs->tags.noexec != tags.noexec) + printf("%sEXEC: ", cs->tags.noexec ? "NO" : ""); + print_member(cs->cmnd); + memcpy(&tags, &cs->tags, sizeof(tags)); + } + } +} - if (yyparse() || parse_error) { - (void) printf("doesn't parse.\n"); - } else { - (void) printf("parses OK.\n\n"); - if (top == 0) - (void) printf("User %s not found\n", pw.pw_name); - else while (top) { - (void) printf("[%d]\n", top-1); - (void) printf("user_match : %d\n", user_matches); - (void) printf("host_match : %d\n", host_matches); - (void) printf("cmnd_match : %d\n", cmnd_matches); - (void) printf("no_passwd : %d\n", no_passwd); - (void) printf("runas_match: %d\n", runas_matches); - (void) printf("runas : %s\n", *user_runas); - if (match[top-1].role) - (void) printf("role : %s\n", match[top-1].role); - if (match[top-1].type) - (void) printf("type : %s\n", match[top-1].type); - top--; +void +print_userspecs() +{ + struct member *m; + struct userspec *us; + + tq_foreach_fwd(&userspecs, us) { + tq_foreach_fwd(&us->users, m) { + if (m != tq_first(&us->users)) + fputs(", ", stdout); + print_member(m); } + putchar('\t'); + print_privilege(us->privileges.first); /* XXX */ + putchar('\n'); } +} - /* Dump aliases. */ - (void) printf("Matching Aliases --\n"); - dumpaliases(); +void +dump_sudoers() +{ + print_defaults(); - exit(0); + putchar('\n'); + alias_apply(print_alias, NULL); + + putchar('\n'); + print_userspecs(); +} + +void +usage() +{ + (void) fprintf(stderr, "usage: %s [-d] [-G grfile] [-g group] [-h host] [-p pwfile] [-u user] [args]\n", getprogname()); + exit(1); } diff --git a/tgetpass.c b/tgetpass.c index 2c94cdb..62faead 100644 --- a/tgetpass.c +++ b/tgetpass.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1996, 1998-2005 Todd C. Miller + * Copyright (c) 1996, 1998-2005, 2007-2008 + * 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 @@ -70,7 +71,7 @@ #include "sudo.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: tgetpass.c,v 1.111.2.7 2008/06/21 00:27:01 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: tgetpass.c,v 1.126 2008/12/09 20:55:49 millert Exp $"; #endif /* lint */ #ifndef TCSASOFT @@ -114,6 +115,7 @@ static volatile sig_atomic_t signo; static void handler __P((int)); static char *getln __P((int, char *, size_t)); +static char *sudo_askpass __P((const char *)); /* * Like getpass(3) but with timeout and echo flags. @@ -132,6 +134,11 @@ tgetpass(prompt, timeout, flags) int input, output, save_errno; (void) fflush(stdout); + + /* If using a helper program to get the password, run it instead. */ + if (ISSET(flags, TGP_ASKPASS) && user_askpass) + return(sudo_askpass(prompt)); + restart: signo = 0; pass = NULL; @@ -147,6 +154,7 @@ restart: * Catch signals that would otherwise cause the user to end * up with echo turned off in the shell. */ + zero_bytes(&sa, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_INTERRUPT; /* don't restart system calls */ sa.sa_handler = handler; @@ -169,8 +177,8 @@ restart: #endif (void) tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); } else { - memset(&term, 0, sizeof(term)); - memset(&oterm, 0, sizeof(oterm)); + zero_bytes(&term, sizeof(term)); + zero_bytes(&oterm, sizeof(oterm)); } /* No output if we are already backgrounded. */ @@ -224,26 +232,74 @@ restart: return(pass); } +/* + * Fork a child and exec sudo-askpass to get the password from the user. + */ +static char * +sudo_askpass(prompt) + const char *prompt; +{ + static char buf[SUDO_PASS_MAX + 1], *pass; + sigaction_t sa, saved_sa_pipe; + int pfd[2]; + pid_t pid; + + if (pipe(pfd) == -1) + error(1, "unable to create pipe"); + + if ((pid = fork()) == -1) + error(1, "unable to fork"); + + if (pid == 0) { + /* child, point stdout to output side of the pipe and exec askpass */ + (void) dup2(pfd[1], STDOUT_FILENO); + set_perms(PERM_FULL_USER); + closefrom(STDERR_FILENO + 1); + execl(user_askpass, user_askpass, prompt, (char *)NULL); + warning("unable to run %s", user_askpass); + _exit(255); + } + + /* Ignore SIGPIPE in case child exits prematurely */ + zero_bytes(&sa, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_IGN; + (void) sigaction(SIGPIPE, &sa, &saved_sa_pipe); + + /* Get response from child (askpass) and restore SIGPIPE handler */ + (void) close(pfd[1]); + pass = getln(pfd[0], buf, sizeof(buf)); + (void) close(pfd[0]); + (void) sigaction(SIGPIPE, &saved_sa_pipe, NULL); + + return(pass); +} + static char * getln(fd, buf, bufsiz) int fd; char *buf; size_t bufsiz; { - char c, *cp; - ssize_t nr; + ssize_t nr = -1; + char *cp = buf; + char c = '\0'; if (bufsiz == 0) { errno = EINVAL; return(NULL); /* sanity */ } - cp = buf; - nr = -1; - while (--bufsiz && (nr = read(fd, &c, 1)) == 1 && c != '\n' && c != '\r') + while (--bufsiz) { + nr = read(fd, &c, 1); + if (nr != 1 || c == '\n' || c == '\r') + break; *cp++ = c; + } *cp = '\0'; - return(nr == -1 ? NULL : buf); + + return(nr == 1 ? buf : NULL); } static void @@ -253,3 +309,13 @@ handler(s) if (s != SIGALRM) signo = s; } + +int +tty_present() +{ + int fd; + + if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) != -1) + close(fd); + return(fd != -1); +} diff --git a/toke.c b/toke.c new file mode 100644 index 0000000..0fd8ef9 --- /dev/null +++ b/toke.c @@ -0,0 +1,3300 @@ +/* $OpenBSD: flex.skl,v 1.10 2007/01/26 14:38:19 tsi Exp $ */ + +/* 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 $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#ifdef __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define yywrap() 1 +#define YY_SKIP_YYWRAP +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *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] = + { 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 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 1, 7, 1, 1, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 22, 22, 23, 24, 1, 1, + 25, 26, 10, 27, 28, 29, 30, 31, 32, 29, + 33, 34, 33, 33, 33, 33, 33, 35, 36, 37, + 33, 38, 39, 40, 41, 42, 43, 44, 33, 33, + 10, 45, 10, 1, 46, 1, 47, 48, 49, 50, + + 51, 52, 53, 53, 54, 53, 53, 55, 56, 57, + 58, 53, 53, 59, 60, 61, 62, 53, 53, 53, + 53, 53, 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, 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, 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, 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, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[63] = + { 0, + 1, 2, 3, 4, 5, 6, 1, 4, 4, 1, + 1, 2, 1, 7, 8, 9, 9, 9, 9, 9, + 9, 9, 9, 10, 6, 4, 1, 9, 9, 9, + 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 11, 12, 13, 13, 13, 13, + 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12 + } ; + +static yyconst short int yy_base[594] = + { 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 + + } ; + +static yyconst short int yy_def[594] = + { 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 + + } ; + +static yyconst short int yy_nxt[3416] = + { 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 + } ; + +static yyconst short int yy_chk[3416] = + { 0, + 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, 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, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 116, 8, 516, 40, 40, 121, 116, + + 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, + 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 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "toke.l" +#define INITIAL 0 +#line 2 "toke.l" +/* + * Copyright (c) 1996, 1998-2005, 2007-2008 + * 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. + * 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. + * + * 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. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) +# include +#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ +#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 $"; +#endif /* lint */ + +extern YYSTYPE yylval; +int sudolineno = 1; +char *sudoers; +static int sawspace = 0; +static int arg_len = 0; +static int arg_size = 0; + +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 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)) + +/* realloc() to size + COMMANDARGINC to make room for command args */ +#define COMMANDARGINC 64 + +#ifdef TRACELEXER +#define LEXTRACE(msg) fputs(msg, stderr) +#else +#define LEXTRACE(msg) +#endif +#define YY_NO_UNPUT 1 +#define GOTDEFS 1 + +#define GOTCMND 2 + +#define STARTDEFS 3 + +#define INDEFS 4 + +#define INSTR 5 + +#line 1413 "lex.yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if defined(YY_STACK_USED) && YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#ifdef __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + if ( yyleng > 0 ) \ + yy_current_buffer->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 113 "toke.l" + +#line 1569 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + 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 ) + 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 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 114 "toke.l" +BEGIN STARTDEFS; + YY_BREAK +case 2: +YY_RULE_SETUP +#line 116 "toke.l" +{ + BEGIN INDEFS; + LEXTRACE("DEFVAR "); + if (!fill(yytext, yyleng)) + yyterminate(); + return(DEFVAR); + } + YY_BREAK + +case 3: +YY_RULE_SETUP +#line 125 "toke.l" +{ + BEGIN STARTDEFS; + LEXTRACE(", "); + return(','); + } /* return ',' */ + YY_BREAK +case 4: +YY_RULE_SETUP +#line 131 "toke.l" +{ + LEXTRACE("= "); + return('='); + } /* return '=' */ + YY_BREAK +case 5: +YY_RULE_SETUP +#line 136 "toke.l" +{ + LEXTRACE("+= "); + return('+'); + } /* return '+' */ + YY_BREAK +case 6: +YY_RULE_SETUP +#line 141 "toke.l" +{ + LEXTRACE("-= "); + return('-'); + } /* return '-' */ + YY_BREAK +case 7: +YY_RULE_SETUP +#line 146 "toke.l" +{ + LEXTRACE("BEGINSTR "); + yylval.string = NULL; + BEGIN INSTR; + } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 152 "toke.l" +{ + LEXTRACE("WORD(2) "); + if (!fill(yytext, yyleng)) + yyterminate(); + return(WORD); + } + YY_BREAK + + +case 9: +YY_RULE_SETUP +#line 161 "toke.l" +{ + /* Line continuation char followed by newline. */ + ++sudolineno; + LEXTRACE("\n"); + } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 167 "toke.l" +{ + LEXTRACE("ENDSTR "); + BEGIN INDEFS; + return(WORD); + } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 173 "toke.l" +{ + LEXTRACE("BACKSLASH "); + if (!append(yytext, yyleng)) + yyterminate(); + } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 179 "toke.l" +{ + LEXTRACE("STRBODY "); + if (!append(yytext, yyleng)) + yyterminate(); + } + YY_BREAK + + +case 13: +YY_RULE_SETUP +#line 187 "toke.l" +{ + /* quoted fnmatch glob char, pass verbatim */ + LEXTRACE("QUOTEDCHAR "); + if (!fill_args(yytext, 2, sawspace)) + yyterminate(); + sawspace = FALSE; + } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 195 "toke.l" +{ + /* quoted sudoers special char, strip backslash */ + LEXTRACE("QUOTEDCHAR "); + if (!fill_args(yytext + 1, 1, sawspace)) + yyterminate(); + sawspace = FALSE; + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 203 "toke.l" +{ + BEGIN INITIAL; + yyless(0); + return(COMMAND); + } /* end of command line args */ + YY_BREAK +case 16: +YY_RULE_SETUP +#line 209 "toke.l" +{ + LEXTRACE("ARG "); + if (!fill_args(yytext, yyleng, sawspace)) + yyterminate(); + sawspace = FALSE; + } /* a command line arg */ + YY_BREAK + +case 17: +YY_RULE_SETUP +#line 217 "toke.l" +{ + char *path; + + if ((path = parse_include(yytext)) == NULL) + yyterminate(); + + LEXTRACE("INCLUDE\n"); + + /* Push current buffer and switch to include file */ + if (!push_include(path)) + yyterminate(); + } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 230 "toke.l" +{ + int n; + for (n = 0; isblank((unsigned char)yytext[n]); n++) + continue; + n += 8; + BEGIN GOTDEFS; + switch (yytext[n++]) { + case ':': + yyless(n); + LEXTRACE("DEFAULTS_USER "); + return(DEFAULTS_USER); + case '>': + yyless(n); + LEXTRACE("DEFAULTS_RUNAS "); + return(DEFAULTS_RUNAS); + case '@': + yyless(n); + LEXTRACE("DEFAULTS_HOST "); + return(DEFAULTS_HOST); + case '!': + yyless(n); + LEXTRACE("DEFAULTS_CMND "); + return(DEFAULTS_CMND); + default: + LEXTRACE("DEFAULTS "); + return(DEFAULTS); + } + } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 259 "toke.l" +{ + int n; + for (n = 0; isblank((unsigned char)yytext[n]); n++) + continue; + switch (yytext[n]) { + case 'H': + LEXTRACE("HOSTALIAS "); + return(HOSTALIAS); + case 'C': + LEXTRACE("CMNDALIAS "); + return(CMNDALIAS); + case 'U': + LEXTRACE("USERALIAS "); + return(USERALIAS); + case 'R': + LEXTRACE("RUNASALIAS "); + return(RUNASALIAS); + } + } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 279 "toke.l" +{ + /* cmnd does not require passwd for this user */ + LEXTRACE("NOPASSWD "); + return(NOPASSWD); + } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 285 "toke.l" +{ + /* cmnd requires passwd for this user */ + LEXTRACE("PASSWD "); + return(PASSWD); + } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 291 "toke.l" +{ + LEXTRACE("NOEXEC "); + return(NOEXEC); + } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 296 "toke.l" +{ + LEXTRACE("EXEC "); + return(EXEC); + } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 301 "toke.l" +{ + LEXTRACE("SETENV "); + return(SETENV); + } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 306 "toke.l" +{ + LEXTRACE("NOSETENV "); + return(NOSETENV); + } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 311 "toke.l" +{ + /* netgroup */ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NETGROUP "); + return(NETGROUP); + } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 319 "toke.l" +{ + /* UN*X group */ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("USERGROUP "); + return(USERGROUP); + } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 327 "toke.l" +{ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return(NTWKADDR); + } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 334 "toke.l" +{ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return(NTWKADDR); + } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 341 "toke.l" +{ + if (!ipv6_valid(yytext)) { + LEXTRACE("ERROR "); + return(ERROR); + } + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return(NTWKADDR); + } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 352 "toke.l" +{ + if (!ipv6_valid(yytext)) { + LEXTRACE("ERROR "); + return(ERROR); + } + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return(NTWKADDR); + } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 363 "toke.l" +{ + if (strcmp(yytext, "ALL") == 0) { + LEXTRACE("ALL "); + return(ALL); + } +#ifdef HAVE_SELINUX + /* XXX - restrict type/role to initial state */ + if (strcmp(yytext, "TYPE") == 0) { + LEXTRACE("TYPE "); + return(TYPE); + } + if (strcmp(yytext, "ROLE") == 0) { + LEXTRACE("ROLE "); + return(ROLE); + } +#endif /* HAVE_SELINUX */ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("ALIAS "); + return(ALIAS); + } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 385 "toke.l" +{ + /* no command args allowed for Defaults!/path */ + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + LEXTRACE("COMMAND "); + return(COMMAND); + } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 393 "toke.l" +{ + BEGIN GOTCMND; + LEXTRACE("COMMAND "); + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + } /* sudo -e */ + YY_BREAK +case 35: +YY_RULE_SETUP +#line 400 "toke.l" +{ + /* directories can't have args... */ + if (yytext[yyleng - 1] == '/') { + LEXTRACE("COMMAND "); + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + return(COMMAND); + } else { + BEGIN GOTCMND; + LEXTRACE("COMMAND "); + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + } + } /* a pathname */ + YY_BREAK +case 36: +YY_RULE_SETUP +#line 415 "toke.l" +{ + /* a word */ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("WORD(4) "); + return(WORD); + } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 423 "toke.l" +{ + LEXTRACE("( "); + return ('('); + } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 428 "toke.l" +{ + LEXTRACE(") "); + return(')'); + } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 433 "toke.l" +{ + LEXTRACE(", "); + return(','); + } /* return ',' */ + YY_BREAK +case 40: +YY_RULE_SETUP +#line 438 "toke.l" +{ + LEXTRACE("= "); + return('='); + } /* return '=' */ + YY_BREAK +case 41: +YY_RULE_SETUP +#line 443 "toke.l" +{ + LEXTRACE(": "); + return(':'); + } /* return ':' */ + YY_BREAK +case 42: +YY_RULE_SETUP +#line 448 "toke.l" +{ + if (yyleng % 2 == 1) + return('!'); /* return '!' */ + } + YY_BREAK +case 43: +YY_RULE_SETUP +#line 453 "toke.l" +{ + BEGIN INITIAL; + ++sudolineno; + LEXTRACE("\n"); + return(COMMENT); + } /* return newline */ + YY_BREAK +case 44: +YY_RULE_SETUP +#line 460 "toke.l" +{ /* throw away space/tabs */ + sawspace = TRUE; /* but remember for fill_args */ + } + YY_BREAK +case 45: +YY_RULE_SETUP +#line 464 "toke.l" +{ + sawspace = TRUE; /* remember for fill_args */ + ++sudolineno; + LEXTRACE("\n\t"); + } /* throw away EOL after \ */ + YY_BREAK +case 46: +YY_RULE_SETUP +#line 470 "toke.l" +{ + BEGIN INITIAL; + ++sudolineno; + LEXTRACE("\n"); + return(COMMENT); + } /* return comments */ + YY_BREAK +case 47: +YY_RULE_SETUP +#line 477 "toke.l" +{ + LEXTRACE("ERROR "); + return(ERROR); + } /* parse error */ + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(GOTDEFS): +case YY_STATE_EOF(GOTCMND): +case YY_STATE_EOF(STARTDEFS): +case YY_STATE_EOF(INDEFS): +case YY_STATE_EOF(INSTR): +#line 482 "toke.l" +{ + if (YY_START != INITIAL) { + BEGIN INITIAL; + LEXTRACE("ERROR "); + return(ERROR); + } + if (!pop_include()) + yyterminate(); + } + YY_BREAK +case 48: +YY_RULE_SETUP +#line 492 "toke.l" +ECHO; + YY_BREAK +#line 2184 "lex.yy.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + 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 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + 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 ) + 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); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + yy_current_buffer->yy_at_bol = (c == '\n'); + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +#include +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + int oerrno = errno; + + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if defined(YY_ALWAYS_INTERACTIVE) && YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if defined(YY_NEVER_INTERACTIVE) && YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + errno = oerrno; + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if defined(YY_MAIN) && YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 492 "toke.l" + +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); + if (dst == NULL) { + yyerror("unable to allocate memory"); + return(FALSE); + } + yylval.string = dst; + + /* 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]; + } + dst[j] = '\0'; + return(TRUE); +} + +static int +append(src, len) + char *src; + int len; +{ + int olen = 0; + + if (yylval.string != NULL) + olen = strlen(yylval.string); + + return(_fill(src, len, olen)); +} + +#define SPECIAL(c) \ + ((c) == ',' || (c) == ':' || (c) == '=' || (c) == ' ' || (c) == '\t' || (c) == '#') + +static int +fill_cmnd(src, len) + char *src; + int len; +{ + char *dst; + int i; + + arg_len = arg_size = 0; + + dst = yylval.command.cmnd = (char *) malloc(len + 1); + if (yylval.command.cmnd == NULL) { + yyerror("unable to allocate memory"); + return(FALSE); + } + + /* Copy the string and collapse any escaped sudo-specific characters. */ + for (i = 0; i < len; i++) { + if (src[i] == '\\' && i != len - 1 && SPECIAL(src[i + 1])) + *dst++ = src[++i]; + else + *dst++ = src[i]; + } + *dst = '\0'; + + yylval.command.args = NULL; + return(TRUE); +} + +static int +fill_args(s, len, addspace) + char *s; + int len; + int addspace; +{ + int new_len; + char *p; + + if (yylval.command.args == NULL) { + addspace = 0; + new_len = len; + } else + new_len = arg_len + len + addspace; + + if (new_len >= arg_size) { + /* Allocate more space than we need for subsequent args */ + while (new_len >= (arg_size += COMMANDARGINC)) + ; + + p = yylval.command.args ? + (char *) realloc(yylval.command.args, arg_size) : + (char *) malloc(arg_size); + if (p == NULL) { + efree(yylval.command.args); + yyerror("unable to allocate memory"); + return(FALSE); + } else + yylval.command.args = p; + } + + /* Efficiently append the arg (with a leading space if needed). */ + p = yylval.command.args + arg_len; + if (addspace) + *p++ = ' '; + if (strlcpy(p, s, arg_size - (p - yylval.command.args)) != len) { + yyerror("fill_args: buffer overflow"); /* paranoia */ + return(FALSE); + } + arg_len = new_len; + return(TRUE); +} + +struct sudoers_state { + YY_BUFFER_STATE bs; + char *path; + int lineno; +}; + +#define MAX_SUDOERS_DEPTH 128 +#define SUDOERS_STACK_INCREMENT 16 + +static int +switch_buffer(path) + char *path; +{ + 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); + } + } + if ((fp = open_sudoers(path, &keepopen)) == NULL) { + yyerror(path); + return(FALSE); + } + state[depth].bs = YY_CURRENT_BUFFER; + state[depth].path = sudoers; + state[depth].lineno = sudolineno; + depth++; + sudolineno = 1; + sudoers = path; + yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); + } 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); + efree(sudoers); + sudoers = state[depth].path; + sudolineno = state[depth].lineno; + keepopen = FALSE; + } + return(TRUE); +} + +static char * +parse_include(base) + char *base; +{ + char *cp, *ep, *path; + int len; + + /* Pull out path from #include line. */ + cp = base + sizeof("#include"); + while (isblank((unsigned char) *cp)) + cp++; + ep = cp; + while (*ep != '\0' && !isspace((unsigned char) *ep)) + ep++; + + /* Make a copy of path and return it. */ + len = (int)(ep - cp); + if ((path = malloc(len + 1)) == NULL) + yyerror("unable to allocate memory"); + memcpy(path, cp, len); + path[len] = '\0'; + + /* Push any excess characters (e.g. comment, newline) back to the lexer */ + if (*ep != '\0') + yyless((int)(ep - base)); + + return(path); +} + +/* + * Check to make sure an IPv6 address does not contain multiple instances + * of the string "::". Assumes strlen(s) >= 1. + * Returns TRUE if address is valid else FALSE. + */ +static int +ipv6_valid(s) + const char *s; +{ + int nmatch = 0; + + for (; *s != '\0'; s++) { + if (s[0] == ':' && s[1] == ':') { + if (++nmatch > 1) + break; + } + if (s[0] == '/') + nmatch = 0; /* reset if we hit netmask */ + } + + return (nmatch <= 1); +} diff --git a/toke.l b/toke.l new file mode 100644 index 0000000..a38da3a --- /dev/null +++ b/toke.l @@ -0,0 +1,719 @@ +%{ +/* + * Copyright (c) 1996, 1998-2005, 2007-2008 + * 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. + * 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. + * + * 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. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) +# include +#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ +#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 $"; +#endif /* lint */ + +extern YYSTYPE yylval; +int sudolineno = 1; +char *sudoers; +static int sawspace = 0; +static int arg_len = 0; +static int arg_size = 0; + +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 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)) + +/* realloc() to size + COMMANDARGINC to make room for command args */ +#define COMMANDARGINC 64 + +#ifdef TRACELEXER +#define LEXTRACE(msg) fputs(msg, stderr) +#else +#define LEXTRACE(msg) +#endif +%} + +HEX16 [0-9A-Fa-f]{1,4} +OCTET (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]) +IPV4ADDR {OCTET}(\.{OCTET}){3} +IPV6ADDR ({HEX16}?:){2,7}{HEX16}?|({HEX16}?:){2,6}:{IPV4ADDR} + +HOSTNAME [[:alnum:]_-]+ +WORD ([^#>!=:,\(\) \t\n\\]|\\[^\n])+ +ID #-?[0-9]+ +PATH \/(\\[\,:= \t#]|[^\,:=\\ \t\n#])+ +ENVAR ([^#!=, \t\n\\\"]|\\[^\n])([^#=, \t\n\\\"]|\\[^\n])* +DEFVAR [a-z_]+ + +%option nounput +%option noyywrap + +%s GOTDEFS +%x GOTCMND +%x STARTDEFS +%x INDEFS +%x INSTR + +%% +[[:blank:]]+ BEGIN STARTDEFS; + +{DEFVAR} { + BEGIN INDEFS; + LEXTRACE("DEFVAR "); + if (!fill(yytext, yyleng)) + yyterminate(); + return(DEFVAR); + } + +{ + , { + BEGIN STARTDEFS; + LEXTRACE(", "); + return(','); + } /* return ',' */ + + = { + LEXTRACE("= "); + return('='); + } /* return '=' */ + + \+= { + LEXTRACE("+= "); + return('+'); + } /* return '+' */ + + -= { + LEXTRACE("-= "); + return('-'); + } /* return '-' */ + + \" { + LEXTRACE("BEGINSTR "); + yylval.string = NULL; + BEGIN INSTR; + } + + {ENVAR} { + LEXTRACE("WORD(2) "); + if (!fill(yytext, yyleng)) + yyterminate(); + return(WORD); + } +} + +{ + \\[[:blank:]]*\n[[:blank:]]* { + /* Line continuation char followed by newline. */ + ++sudolineno; + LEXTRACE("\n"); + } + + \" { + LEXTRACE("ENDSTR "); + BEGIN INDEFS; + return(WORD); + } + + \\ { + LEXTRACE("BACKSLASH "); + if (!append(yytext, yyleng)) + yyterminate(); + } + + ([^\"\n\\]|\\\")+ { + LEXTRACE("STRBODY "); + if (!append(yytext, yyleng)) + yyterminate(); + } +} + +{ + \\[\*\?\[\]\!] { + /* quoted fnmatch glob char, pass verbatim */ + LEXTRACE("QUOTEDCHAR "); + if (!fill_args(yytext, 2, sawspace)) + yyterminate(); + sawspace = FALSE; + } + + \\[:\\,= \t#] { + /* quoted sudoers special char, strip backslash */ + LEXTRACE("QUOTEDCHAR "); + if (!fill_args(yytext + 1, 1, sawspace)) + yyterminate(); + sawspace = FALSE; + } + + [#:\,=\n] { + BEGIN INITIAL; + yyless(0); + return(COMMAND); + } /* end of command line args */ + + [^\\:, \t\n]+ { + LEXTRACE("ARG "); + if (!fill_args(yytext, yyleng, sawspace)) + yyterminate(); + sawspace = FALSE; + } /* a command line arg */ +} + +^#include[[:blank:]]+\/.*\n { + char *path; + + if ((path = parse_include(yytext)) == NULL) + yyterminate(); + + LEXTRACE("INCLUDE\n"); + + /* Push current buffer and switch to include file */ + if (!push_include(path)) + yyterminate(); + } + +^[[:blank:]]*Defaults([:@>\!]{WORD})? { + int n; + for (n = 0; isblank((unsigned char)yytext[n]); n++) + continue; + n += 8; + BEGIN GOTDEFS; + switch (yytext[n++]) { + case ':': + yyless(n); + LEXTRACE("DEFAULTS_USER "); + return(DEFAULTS_USER); + case '>': + yyless(n); + LEXTRACE("DEFAULTS_RUNAS "); + return(DEFAULTS_RUNAS); + case '@': + yyless(n); + LEXTRACE("DEFAULTS_HOST "); + return(DEFAULTS_HOST); + case '!': + yyless(n); + LEXTRACE("DEFAULTS_CMND "); + return(DEFAULTS_CMND); + default: + LEXTRACE("DEFAULTS "); + return(DEFAULTS); + } + } + +^[[:blank:]]*(Host|Cmnd|User|Runas)_Alias { + int n; + for (n = 0; isblank((unsigned char)yytext[n]); n++) + continue; + switch (yytext[n]) { + case 'H': + LEXTRACE("HOSTALIAS "); + return(HOSTALIAS); + case 'C': + LEXTRACE("CMNDALIAS "); + return(CMNDALIAS); + case 'U': + LEXTRACE("USERALIAS "); + return(USERALIAS); + case 'R': + LEXTRACE("RUNASALIAS "); + return(RUNASALIAS); + } + } + +NOPASSWD[[:blank:]]*: { + /* cmnd does not require passwd for this user */ + LEXTRACE("NOPASSWD "); + return(NOPASSWD); + } + +PASSWD[[:blank:]]*: { + /* cmnd requires passwd for this user */ + LEXTRACE("PASSWD "); + return(PASSWD); + } + +NOEXEC[[:blank:]]*: { + LEXTRACE("NOEXEC "); + return(NOEXEC); + } + +EXEC[[:blank:]]*: { + LEXTRACE("EXEC "); + return(EXEC); + } + +SETENV[[:blank:]]*: { + LEXTRACE("SETENV "); + return(SETENV); + } + +NOSETENV[[:blank:]]*: { + LEXTRACE("NOSETENV "); + return(NOSETENV); + } + +\+{WORD} { + /* netgroup */ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NETGROUP "); + return(NETGROUP); + } + +\%{WORD} { + /* UN*X group */ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("USERGROUP "); + return(USERGROUP); + } + +{IPV4ADDR}(\/{IPV4ADDR})? { + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return(NTWKADDR); + } + +{IPV4ADDR}\/([12][0-9]*|3[0-2]*) { + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return(NTWKADDR); + } + +{IPV6ADDR}(\/{IPV6ADDR})? { + if (!ipv6_valid(yytext)) { + LEXTRACE("ERROR "); + return(ERROR); + } + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return(NTWKADDR); + } + +{IPV6ADDR}\/([0-9]|[1-9][0-9]|1[01][0-9]|12[0-8]) { + if (!ipv6_valid(yytext)) { + LEXTRACE("ERROR "); + return(ERROR); + } + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return(NTWKADDR); + } + +[[:upper:]][[:upper:][:digit:]_]* { + if (strcmp(yytext, "ALL") == 0) { + LEXTRACE("ALL "); + return(ALL); + } +#ifdef HAVE_SELINUX + /* XXX - restrict type/role to initial state */ + if (strcmp(yytext, "TYPE") == 0) { + LEXTRACE("TYPE "); + return(TYPE); + } + if (strcmp(yytext, "ROLE") == 0) { + LEXTRACE("ROLE "); + return(ROLE); + } +#endif /* HAVE_SELINUX */ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("ALIAS "); + return(ALIAS); + } + +({PATH}|sudoedit) { + /* no command args allowed for Defaults!/path */ + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + LEXTRACE("COMMAND "); + return(COMMAND); + } + +sudoedit { + BEGIN GOTCMND; + LEXTRACE("COMMAND "); + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + } /* sudo -e */ + +{PATH} { + /* directories can't have args... */ + if (yytext[yyleng - 1] == '/') { + LEXTRACE("COMMAND "); + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + return(COMMAND); + } else { + BEGIN GOTCMND; + LEXTRACE("COMMAND "); + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + } + } /* a pathname */ + +({ID}|{WORD}) { + /* a word */ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("WORD(4) "); + return(WORD); + } + +\( { + LEXTRACE("( "); + return ('('); + } + +\) { + LEXTRACE(") "); + return(')'); + } + +, { + LEXTRACE(", "); + return(','); + } /* return ',' */ + += { + LEXTRACE("= "); + return('='); + } /* return '=' */ + +: { + LEXTRACE(": "); + return(':'); + } /* return ':' */ + +<*>!+ { + if (yyleng % 2 == 1) + return('!'); /* return '!' */ + } + +<*>\n { + BEGIN INITIAL; + ++sudolineno; + LEXTRACE("\n"); + return(COMMENT); + } /* return newline */ + +<*>[[:blank:]]+ { /* throw away space/tabs */ + sawspace = TRUE; /* but remember for fill_args */ + } + +<*>\\[[:blank:]]*\n { + sawspace = TRUE; /* remember for fill_args */ + ++sudolineno; + LEXTRACE("\n\t"); + } /* throw away EOL after \ */ + +#([^\n0-9-].*)?\n { + BEGIN INITIAL; + ++sudolineno; + LEXTRACE("\n"); + return(COMMENT); + } /* return comments */ + +<*>. { + LEXTRACE("ERROR "); + return(ERROR); + } /* parse error */ + +<*><> { + if (YY_START != INITIAL) { + BEGIN INITIAL; + LEXTRACE("ERROR "); + return(ERROR); + } + if (!pop_include()) + yyterminate(); + } + +%% +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); + if (dst == NULL) { + yyerror("unable to allocate memory"); + return(FALSE); + } + yylval.string = dst; + + /* 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]; + } + dst[j] = '\0'; + return(TRUE); +} + +static int +append(src, len) + char *src; + int len; +{ + int olen = 0; + + if (yylval.string != NULL) + olen = strlen(yylval.string); + + return(_fill(src, len, olen)); +} + +#define SPECIAL(c) \ + ((c) == ',' || (c) == ':' || (c) == '=' || (c) == ' ' || (c) == '\t' || (c) == '#') + +static int +fill_cmnd(src, len) + char *src; + int len; +{ + char *dst; + int i; + + arg_len = arg_size = 0; + + dst = yylval.command.cmnd = (char *) malloc(len + 1); + if (yylval.command.cmnd == NULL) { + yyerror("unable to allocate memory"); + return(FALSE); + } + + /* Copy the string and collapse any escaped sudo-specific characters. */ + for (i = 0; i < len; i++) { + if (src[i] == '\\' && i != len - 1 && SPECIAL(src[i + 1])) + *dst++ = src[++i]; + else + *dst++ = src[i]; + } + *dst = '\0'; + + yylval.command.args = NULL; + return(TRUE); +} + +static int +fill_args(s, len, addspace) + char *s; + int len; + int addspace; +{ + int new_len; + char *p; + + if (yylval.command.args == NULL) { + addspace = 0; + new_len = len; + } else + new_len = arg_len + len + addspace; + + if (new_len >= arg_size) { + /* Allocate more space than we need for subsequent args */ + while (new_len >= (arg_size += COMMANDARGINC)) + ; + + p = yylval.command.args ? + (char *) realloc(yylval.command.args, arg_size) : + (char *) malloc(arg_size); + if (p == NULL) { + efree(yylval.command.args); + yyerror("unable to allocate memory"); + return(FALSE); + } else + yylval.command.args = p; + } + + /* Efficiently append the arg (with a leading space if needed). */ + p = yylval.command.args + arg_len; + if (addspace) + *p++ = ' '; + if (strlcpy(p, s, arg_size - (p - yylval.command.args)) != len) { + yyerror("fill_args: buffer overflow"); /* paranoia */ + return(FALSE); + } + arg_len = new_len; + return(TRUE); +} + +struct sudoers_state { + YY_BUFFER_STATE bs; + char *path; + int lineno; +}; + +#define MAX_SUDOERS_DEPTH 128 +#define SUDOERS_STACK_INCREMENT 16 + +static int +switch_buffer(path) + char *path; +{ + 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); + } + } + if ((fp = open_sudoers(path, &keepopen)) == NULL) { + yyerror(path); + return(FALSE); + } + state[depth].bs = YY_CURRENT_BUFFER; + state[depth].path = sudoers; + state[depth].lineno = sudolineno; + depth++; + sudolineno = 1; + sudoers = path; + yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); + } 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); + efree(sudoers); + sudoers = state[depth].path; + sudolineno = state[depth].lineno; + keepopen = FALSE; + } + return(TRUE); +} + +static char * +parse_include(base) + char *base; +{ + char *cp, *ep, *path; + int len; + + /* Pull out path from #include line. */ + cp = base + sizeof("#include"); + while (isblank((unsigned char) *cp)) + cp++; + ep = cp; + while (*ep != '\0' && !isspace((unsigned char) *ep)) + ep++; + + /* Make a copy of path and return it. */ + len = (int)(ep - cp); + if ((path = malloc(len + 1)) == NULL) + yyerror("unable to allocate memory"); + memcpy(path, cp, len); + path[len] = '\0'; + + /* Push any excess characters (e.g. comment, newline) back to the lexer */ + if (*ep != '\0') + yyless((int)(ep - base)); + + return(path); +} + +/* + * Check to make sure an IPv6 address does not contain multiple instances + * of the string "::". Assumes strlen(s) >= 1. + * Returns TRUE if address is valid else FALSE. + */ +static int +ipv6_valid(s) + const char *s; +{ + int nmatch = 0; + + for (; *s != '\0'; s++) { + if (s[0] == ':' && s[1] == ':') { + if (++nmatch > 1) + break; + } + if (s[0] == '/') + nmatch = 0; /* reset if we hit netmask */ + } + + return (nmatch <= 1); +} diff --git a/tsgetgrpw.c b/tsgetgrpw.c new file mode 100644 index 0000000..7f35269 --- /dev/null +++ b/tsgetgrpw.c @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2005,2008 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. + */ + +/* + * Trivial replacements for the libc get{gr,pw}{uid,nam}() routines + * for use by testsudoers in the sudo test harness. + * We need our own since many platforms don't provide set{pw,gr}file(). + */ + +#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 */ +#include +#include +#include + +#include "sudo.h" + +#ifndef LINE_MAX +# define LINE_MAX 2048 +#endif + +#undef GRMEM_MAX +#define GRMEM_MAX 200 + +static FILE *pwf; +static const char *pwfile = "/etc/passwd"; +static int pw_stayopen; + +static FILE *grf; +static const char *grfile = "/etc/group"; +static int gr_stayopen; + +void ts_setgrfile __P((const char *)); +void ts_setgrent __P((void)); +void ts_endgrent __P((void)); +struct group *ts_getgrent __P((void)); +struct group *ts_getgrnam __P((const char *)); +struct group *ts_getgrgid __P((gid_t)); + +void ts_setpwfile __P((const char *)); +void ts_setpwent __P((void)); +void ts_endpwent __P((void)); +struct passwd *ts_getpwent __P((void)); +struct passwd *ts_getpwnam __P((const char *)); +struct passwd *ts_getpwuid __P((uid_t)); + +void +ts_setpwfile(file) + const char *file; +{ + pwfile = file; + if (pwf != NULL) + ts_endpwent(); +} + +void +ts_setpwent() +{ + if (pwf == NULL) + pwf = fopen(pwfile, "r"); + else + rewind(pwf); + pw_stayopen = 1; +} + +void +ts_endpwent() +{ + if (pwf != NULL) { + fclose(pwf); + pwf = NULL; + } + pw_stayopen = 0; +} + +struct passwd * +ts_getpwent() +{ + static struct passwd pw; + static char pwbuf[LINE_MAX]; + size_t len; + char *cp, *colon; + + if ((colon = fgets(pwbuf, sizeof(pwbuf), pwf)) == NULL) + return(NULL); + + zero_bytes(&pw, sizeof(pw)); + if ((colon = strchr(cp = colon, ':')) == NULL) + return(NULL); + *colon++ = '\0'; + pw.pw_name = cp; + if ((colon = strchr(cp = colon, ':')) == NULL) + return(NULL); + *colon++ = '\0'; + pw.pw_passwd = cp; + if ((colon = strchr(cp = colon, ':')) == NULL) + return(NULL); + *colon++ = '\0'; + pw.pw_uid = atoi(cp); + if ((colon = strchr(cp = colon, ':')) == NULL) + return(NULL); + *colon++ = '\0'; + pw.pw_gid = atoi(cp); + if ((colon = strchr(cp = colon, ':')) == NULL) + return(NULL); + *colon++ = '\0'; + pw.pw_gecos = cp; + if ((colon = strchr(cp = colon, ':')) == NULL) + return(NULL); + *colon++ = '\0'; + pw.pw_dir = cp; + pw.pw_shell = colon; + len = strlen(colon); + if (len > 0 && colon[len - 1] == '\n') + colon[len - 1] = '\0'; + return(&pw); +} + +struct passwd * +ts_getpwnam(name) + const char *name; +{ + struct passwd *pw; + + if (pwf != NULL) + rewind(pwf); + else if ((pwf = fopen(pwfile, "r")) == NULL) + return(NULL); + while ((pw = ts_getpwent()) != NULL) { + if (strcmp(pw->pw_name, name) == 0) + break; + } + if (!pw_stayopen) { + fclose(pwf); + pwf = NULL; + } + return(pw); +} + +struct passwd * +ts_getpwuid(uid) + uid_t uid; +{ + struct passwd *pw; + + if (pwf != NULL) + rewind(pwf); + else if ((pwf = fopen(pwfile, "r")) == NULL) + return(NULL); + while ((pw = ts_getpwent()) != NULL) { + if (pw->pw_uid == uid) + break; + } + if (!pw_stayopen) { + fclose(pwf); + pwf = NULL; + } + return(pw); +} + +void +ts_setgrfile(file) + const char *file; +{ + grfile = file; + if (grf != NULL) + ts_endgrent(); +} + +void +ts_setgrent() +{ + if (grf == NULL) + grf = fopen(grfile, "r"); + else + rewind(grf); + gr_stayopen = 1; +} + +void +ts_endgrent() +{ + if (grf != NULL) { + fclose(grf); + grf = NULL; + } + gr_stayopen = 0; +} + +struct group * +ts_getgrent() +{ + static struct group gr; + static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1]; + size_t len; + char *cp, *colon; + int n; + + if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL) + return(NULL); + + zero_bytes(&gr, sizeof(gr)); + if ((colon = strchr(cp = colon, ':')) == NULL) + return(NULL); + *colon++ = '\0'; + gr.gr_name = cp; + if ((colon = strchr(cp = colon, ':')) == NULL) + return(NULL); + *colon++ = '\0'; + gr.gr_passwd = cp; + if ((colon = strchr(cp = colon, ':')) == NULL) + return(NULL); + *colon++ = '\0'; + gr.gr_gid = atoi(cp); + len = strlen(colon); + if (len > 0 && colon[len - 1] == '\n') + colon[len - 1] = '\0'; + if (*colon != '\0') { + gr.gr_mem = gr_mem; + cp = strtok(colon, ","); + for (n = 0; cp != NULL && n < GRMEM_MAX; n++) { + gr.gr_mem[n] = cp; + cp = strtok(NULL, ","); + } + gr.gr_mem[n++] = NULL; + } else + gr.gr_mem = NULL; + return(&gr); +} + +struct group * +ts_getgrnam(name) + const char *name; +{ + struct group *gr; + + if (grf != NULL) + rewind(grf); + else if ((grf = fopen(grfile, "r")) == NULL) + return(NULL); + while ((gr = ts_getgrent()) != NULL) { + if (strcmp(gr->gr_name, name) == 0) + break; + } + if (!gr_stayopen) { + fclose(grf); + grf = NULL; + } + return(gr); +} + +struct group * +ts_getgrgid(gid) + gid_t gid; +{ + struct group *gr; + + if (grf != NULL) + rewind(grf); + else if ((grf = fopen(grfile, "r")) == NULL) + return(NULL); + while ((gr = ts_getgrent()) != NULL) { + if (gr->gr_gid == gid) + break; + } + if (!gr_stayopen) { + fclose(grf); + grf = NULL; + } + return(gr); +} diff --git a/utimes.c b/utimes.c index ae163cd..6d260c4 100644 --- a/utimes.c +++ b/utimes.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 Todd C. Miller + * Copyright (c) 2004-2005, 2007 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 @@ -20,7 +20,7 @@ #include #include #if TIME_WITH_SYS_TIME -#include +# include #endif #ifdef HAVE_UTIME_H @@ -32,7 +32,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: utimes.c,v 1.8.2.3 2007/06/12 00:56:43 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: utimes.c,v 1.10 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ #ifndef HAVE_UTIMES diff --git a/version.h b/version.h index c9459cc..fa354e0 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 1996, 1998-2005 Todd C. Miller + * Copyright (c) 1996, 1998-2005, 2008 + * 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 @@ -17,12 +18,12 @@ * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. * - * $Sudo: version.h,v 1.66.2.20 2008/06/22 20:29:03 millert Exp $ + * $Sudo: version.h,v 1.71 2008/11/09 14:13:12 millert Exp $ */ #ifndef _SUDO_VERSION_H #define _SUDO_VERSION_H -static const char version[] = "1.6.9p17"; +static const char version[] = "1.7.0"; #endif /* _SUDO_VERSION_H */ diff --git a/visudo.c b/visudo.c index 4fdcd8f..81b5718 100644 --- a/visudo.c +++ b/visudo.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1996, 1998-2005 Todd C. Miller + * Copyright (c) 1996, 1998-2005, 2007-2008 + * 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 @@ -33,6 +34,7 @@ #include #include #include +#include #include #ifndef __TANDEM # include @@ -57,72 +59,72 @@ #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ -#ifdef HAVE_ERR_H -# include -#else -# include "emul/err.h" -#endif /* HAVE_ERR_H */ #include #include -#if TIME_WITH_SYS_TIME -# include -#endif +#include #include #include #include +#include +#include +#include +#if TIME_WITH_SYS_TIME +# include +#endif +#ifdef __STDC__ +# include +#else +# include +#endif #ifndef HAVE_TIMESPEC # include #endif #include "sudo.h" +#include "interfaces.h" +#include "parse.h" +#include #include "version.h" #ifndef lint -__unused static const char rcsid[] = "$Sudo: visudo.c,v 1.166.2.11 2008/06/21 00:47:52 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: visudo.c,v 1.223 2008/11/22 15:12:26 millert Exp $"; #endif /* lint */ struct sudoersfile { char *path; - char *tpath; int fd; - off_t orig_size; - struct timespec orig_mtim; + char *tpath; + int tfd; + int modified; + struct sudoersfile *next; }; /* * Function prototypes */ -static void usage __P((void)) __attribute__((__noreturn__)); -static char whatnow __P((void)); -static RETSIGTYPE Exit __P((int)); -static void edit_sudoers __P((struct sudoersfile *, char *, char *, int)); -static void visudo __P((struct sudoersfile *, char *, char *)); -static void setup_signals __P((void)); -static void install_sudoers __P((struct sudoersfile *, int)); -static int check_syntax __P(()); -static int run_command __P((char *, char **)); +static RETSIGTYPE quit __P((int)); static char *get_args __P((char *)); static char *get_editor __P((char **)); -static FILE *open_sudoers __P((struct sudoersfile *)); - -int command_matches __P((char *, char *)); -int addr_matches __P((char *)); -int hostname_matches __P((char *, char *, char *)); -int netgr_matches __P((char *, char *, char *, char *)); -int usergr_matches __P((char *, char *, struct passwd *)); -int userpw_matches __P((char *, char *, struct passwd *)); -void init_parser __P((void)); -void yyerror __P((char *)); -void yyrestart __P((FILE *)); +static char whatnow __P((void)); +static int check_aliases __P((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 setup_signals __P((void)); +static void usage __P((void)) __attribute__((__noreturn__)); + +extern void yyerror __P((const char *)); +extern void yyrestart __P((FILE *)); /* * External globals exported by the parser */ extern FILE *yyin; -extern int errorlineno; -extern int pedantic; -extern int quiet; - +extern char *sudoers, *errorfile; +extern int errorlineno, parse_error; /* For getopt(3) */ extern char *optarg; extern int optind; @@ -130,26 +132,28 @@ extern int optind; /* * Globals */ +int Argc; char **Argv; +int num_interfaces; +struct interface *interfaces; struct sudo_user sudo_user; -int Argc, parse_error = FALSE; -static struct sudoersfile sudoers; +struct passwd *list_pw; +static struct sudoerslist { + struct sudoersfile *first, *last; +} sudoerslist; int main(argc, argv) int argc; char **argv; { - char *args, *editor; - int ch, checkonly, n, oldperms; - - /* Initialize sudoers struct. */ - sudoers.path = _PATH_SUDOERS; - sudoers.tpath = _PATH_SUDOERS_TMP; - sudoers.fd = -1; - - /* Warn about aliases that are used before being defined. */ - pedantic = 1; + struct sudoersfile *sp; + char *args, *editor, *sudoers_path; + int ch, checkonly, quiet, strict, oldperms; +#if defined(SUDO_DEVEL) && defined(__OpenBSD__) + extern char *malloc_options; + malloc_options = "AFGJPR"; +#endif Argv = argv; if ((Argc = argc) < 1) @@ -158,7 +162,8 @@ main(argc, argv) /* * Arg handling. */ - checkonly = oldperms = FALSE; + checkonly = oldperms = quiet = strict = FALSE; + sudoers_path = _PATH_SUDOERS; while ((ch = getopt(argc, argv, "Vcf:sq")) != -1) { switch (ch) { case 'V': @@ -167,13 +172,12 @@ main(argc, argv) case 'c': checkonly++; /* check mode */ break; - case 'f': /* sudoers file path */ - sudoers.path = optarg; - easprintf(&sudoers.tpath, "%s.tmp", optarg); + case 'f': + sudoers_path = optarg; /* sudoers file path */ oldperms = TRUE; break; case 's': - pedantic++; /* strict mode */ + strict++; /* strict mode */ break; case 'q': quiet++; /* quiet mode */ @@ -187,59 +191,115 @@ main(argc, argv) if (argc) usage(); + sudo_setpwent(); + sudo_setgrent(); + /* Mock up a fake sudo_user struct. */ user_host = user_shost = user_cmnd = ""; - if ((sudo_user.pw = getpwuid(getuid())) == NULL) - errx(1, "you don't exist in the passwd database"); + if ((sudo_user.pw = sudo_getpwuid(getuid())) == NULL) + errorx(1, "you don't exist in the passwd database"); /* Setup defaults data structures. */ init_defaults(); if (checkonly) - exit(check_syntax()); + exit(check_syntax(sudoers_path, quiet, strict)); /* - * Open and 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)) == NULL) - err(1, "%s", sudoers.path); - n = quiet; - quiet = 1; - init_parser(); + * 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) + error(1, "%s", sudoers_path); + init_parser(sudoers_path, 0); yyparse(); - parse_error = FALSE; - quiet = n; + (void) update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER); - /* Edit sudoers, check for parse errors and re-edit on failure. */ editor = get_editor(&args); - visudo(&sudoers, editor, args); - /* Install the new sudoers file. */ - install_sudoers(&sudoers, oldperms); + /* Install signal handlers to clean up temp files if we are killed. */ + setup_signals(); + + /* Edit the sudoers file(s) */ + tq_foreach_fwd(&sudoerslist, sp) { + if (sp != tq_first(&sudoerslist)) { + printf("press return to edit %s: ", sp->path); + while ((ch = getchar()) != EOF && ch != '\n') + continue; + } + edit_sudoers(sp, editor, args, -1); + } + + /* Check edited files for a parse error and re-edit any that fail. */ + reparse_sudoers(editor, args, strict, quiet); + + /* Install the sudoers temp files. */ + tq_foreach_fwd(&sudoerslist, sp) { + if (!sp->modified) + (void) unlink(sp->tpath); + else + (void) install_sudoers(sp, oldperms); + } exit(0); } /* - * Edit the sudoers file. + * Edit each sudoers file. * Returns TRUE on success, else FALSE. */ -static void +static int edit_sudoers(sp, editor, args, lineno) struct sudoersfile *sp; char *editor, *args; int lineno; { + int tfd; /* sudoers temp file descriptor */ + int modified; /* was the file modified? */ int ac; /* argument count */ char **av; /* argument vector for run_command */ char *cp; /* scratch char pointer */ + char buf[PATH_MAX*2]; /* buffer used for copying files */ char linestr[64]; /* string version of lineno */ struct timespec ts1, ts2; /* time before and after edit */ + struct timespec orig_mtim; /* starting mtime of sudoers file */ + off_t orig_size; /* starting size of sudoers file */ + ssize_t nread; /* number of bytes read */ struct stat sb; /* stat buffer */ - /* Make timestamp on temp file match original. */ - (void) touch(-1, sp->tpath, &sp->orig_mtim); +#ifdef HAVE_FSTAT + if (fstat(sp->fd, &sb) == -1) +#else + if (stat(sp->path, &sb) == -1) +#endif + error(1, "can't stat %s", sp->path); + orig_size = sb.st_size; + orig_mtim.tv_sec = mtim_getsec(sb); + orig_mtim.tv_nsec = mtim_getnsec(sb); + + /* Create the temp file if needed and set timestamp. */ + if (sp->tpath == NULL) { + easprintf(&sp->tpath, "%s.tmp", sp->path); + tfd = open(sp->tpath, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (tfd < 0) + error(1, "%s", sp->tpath); + + /* Copy sp->path -> sp->tpath and reset the mtime. */ + if (orig_size != 0) { + (void) lseek(sp->fd, (off_t)0, SEEK_SET); + while ((nread = read(sp->fd, buf, sizeof(buf))) > 0) + if (write(tfd, buf, nread) != nread) + error(1, "write error"); + + /* Add missing newline at EOF if needed. */ + if (nread > 0 && buf[nread - 1] != '\n') { + buf[0] = '\n'; + write(tfd, buf, 1); + } + } + (void) close(tfd); + } + (void) touch(-1, sp->tpath, &orig_mtim); /* Find the length of the argument vector */ ac = 3 + (lineno > 0); @@ -288,24 +348,26 @@ edit_sudoers(sp, editor, args, lineno) * Sanity checks. */ if (stat(sp->tpath, &sb) < 0) { - warnx("cannot stat temporary file (%s), %s unchanged", + warningx("cannot stat temporary file (%s), %s unchanged", sp->tpath, sp->path); - Exit(-1); + return(FALSE); } - if (sb.st_size == 0) { - warnx("zero length temporary file (%s), %s unchanged", + if (sb.st_size == 0 && orig_size != 0) { + warningx("zero length temporary file (%s), %s unchanged", sp->tpath, sp->path); - Exit(-1); + sp->modified = TRUE; + return(FALSE); } } else { - warnx("editor (%s) failed, %s unchanged", editor, sp->path); - Exit(-1); + warningx("editor (%s) failed, %s unchanged", editor, sp->path); + return(FALSE); } - /* Check to see if the user changed the file. */ - if (sp->orig_size == sb.st_size && - sp->orig_mtim.tv_sec == mtim_getsec(sb) && - sp->orig_mtim.tv_nsec == mtim_getnsec(sb)) { + /* Set modified bit if use changed the file. */ + modified = TRUE; + if (orig_size == sb.st_size && + orig_mtim.tv_sec == mtim_getsec(sb) && + orig_mtim.tv_nsec == mtim_getnsec(sb)) { /* * If mtime and size match but the user spent no measurable * time in the editor we can't tell if the file was changed. @@ -315,55 +377,59 @@ edit_sudoers(sp, editor, args, lineno) #else timespecsub(&ts1, &ts2, &ts2); #endif - if (timespecisset(&ts2)) { - warnx("%s unchanged", sp->tpath); - Exit(0); - } + if (timespecisset(&ts2)) + modified = FALSE; } + + /* + * If modified in this edit session, mark as modified. + */ + if (modified) + sp->modified = modified; + else + warningx("%s unchanged", sp->tpath); + + return(TRUE); } /* * Parse sudoers after editing and re-edit any ones that caused a parse error. * Returns TRUE on success, else FALSE. */ -static void -visudo(sp, editor, args) - struct sudoersfile *sp; +static int +reparse_sudoers(editor, args, strict, quiet) char *editor, *args; + int strict, quiet; { + struct sudoersfile *sp, *last; + FILE *fp; int ch; /* - * Parse the edited sudoers file and do sanity checking + * Parse the edited sudoers files and do sanity checking */ do { - edit_sudoers(sp, editor, args, errorlineno); - - yyin = fopen(sp->tpath, "r+"); - if (yyin == NULL) { - warnx("can't re-open temporary file (%s), %s unchanged.", + sp = tq_first(&sudoerslist); + last = tq_last(&sudoerslist); + fp = fopen(sp->tpath, "r+"); + if (fp == NULL) + errorx(1, "can't re-open temporary file (%s), %s unchanged.", sp->tpath, sp->path); - Exit(-1); - } - - /* Add missing newline at EOF if needed. */ - if (fseek(yyin, -1, SEEK_END) == 0 && (ch = fgetc(yyin)) != '\n') - fputc('\n', yyin); - rewind(yyin); /* Clean slate for each parse */ - user_runas = NULL; init_defaults(); - init_parser(); + init_parser(sp->path, quiet); /* Parse the sudoers temp file */ - yyrestart(yyin); + yyrestart(fp); if (yyparse() && parse_error != TRUE) { - warnx("unabled to parse temporary file (%s), unknown error", + warningx("unabled to parse temporary file (%s), unknown error", sp->tpath); parse_error = TRUE; } fclose(yyin); + if (check_aliases(strict) != 0) + parse_error = TRUE; /* * Got an error, prompt the user for what to do now @@ -372,18 +438,40 @@ visudo(sp, editor, args) switch (whatnow()) { case 'Q' : parse_error = FALSE; /* ignore parse error */ break; - case 'x' : Exit(0); + case 'x' : cleanup(0); + exit(0); break; } } + if (parse_error) { + /* Edit file with the parse error */ + tq_foreach_fwd(&sudoerslist, sp) { + if (errorfile == NULL || strcmp(sp->path, errorfile) == 0) { + edit_sudoers(sp, editor, args, errorlineno); + break; + } + } + if (sp == NULL) + errorx(1, "internal error, can't find %s in list!", sudoers); + } + + /* If any new #include directives were added, edit them too. */ + for (sp = last->next; sp != NULL; sp = sp->next) { + printf("press return to edit %s: ", sp->path); + while ((ch = getchar()) != EOF && ch != '\n') + continue; + edit_sudoers(sp, editor, args, errorlineno); + } } while (parse_error); + + return(TRUE); } /* * Set the owner and mode on a sudoers temp file and * move it into place. Returns TRUE on success, else FALSE. */ -static void +static int install_sudoers(sp, oldperms) struct sudoersfile *sp; int oldperms; @@ -401,18 +489,19 @@ install_sudoers(sp, oldperms) #else if (stat(sp->path, &sb) == -1) #endif - err(1, "can't stat %s", sp->path); + error(1, "can't stat %s", sp->path); (void) chown(sp->tpath, sb.st_uid, sb.st_gid); (void) chmod(sp->tpath, sb.st_mode & 0777); } else { if (chown(sp->tpath, SUDOERS_UID, SUDOERS_GID) != 0) { - warn("unable to set (uid, gid) of %s to (%d, %d)", + warning("unable to set (uid, gid) of %s to (%d, %d)", sp->tpath, SUDOERS_UID, SUDOERS_GID); - Exit(-1); + return(FALSE); } if (chmod(sp->tpath, SUDOERS_MODE) != 0) { - warn("unable to change mode of %s to 0%o", sp->tpath, SUDOERS_MODE); - Exit(-1); + warning("unable to change mode of %s to 0%o", sp->tpath, + SUDOERS_MODE); + return(FALSE); } } @@ -421,10 +510,13 @@ install_sudoers(sp, oldperms) * rename(2)'d to sp->path. If the rename(2) fails we try using * mv(1) in case sp->tpath and sp->path are on different file systems. */ - if (rename(sp->tpath, sp->path) != 0) { + if (rename(sp->tpath, sp->path) == 0) { + efree(sp->tpath); + sp->tpath = NULL; + } else { if (errno == EXDEV) { char *av[4]; - warnx("%s and %s not on the same file system, using mv to rename", + warningx("%s and %s not on the same file system, using mv to rename", sp->tpath, sp->path); /* Build up argument vector for the command */ @@ -438,98 +530,64 @@ install_sudoers(sp, oldperms) /* And run it... */ if (run_command(_PATH_MV, av)) { - warnx("command failed: '%s %s %s', %s unchanged", + warningx("command failed: '%s %s %s', %s unchanged", _PATH_MV, sp->tpath, sp->path, sp->path); - Exit(-1); + (void) unlink(sp->tpath); + efree(sp->tpath); + sp->tpath = NULL; + return(FALSE); } + efree(sp->tpath); + sp->tpath = NULL; } else { - warn("error renaming %s, %s unchanged", sp->tpath, sp->path); - Exit(-1); + warning("error renaming %s, %s unchanged", sp->tpath, sp->path); + (void) unlink(sp->tpath); + return(FALSE); } } -} - -/* - * Dummy *_matches routines. - * These exist to allow us to use the same parser as sudo(8). - */ -int -command_matches(path, sudoers_args) - char *path; - char *sudoers_args; -{ - return(TRUE); -} - -int -addr_matches(n) - char *n; -{ return(TRUE); } -int -hostname_matches(s, l, p) - char *s, *l, *p; -{ - return(TRUE); -} - -int -usergr_matches(g, u, pw) - char *g, *u; - struct passwd *pw; +/* STUB */ +void +set_fqdn() { - return(TRUE); + return; } -int -userpw_matches(s, u, pw) - char *s, *u; - struct passwd *pw; +/* STUB */ +void +init_envtables() { - return(TRUE); + return; } +/* STUB */ int -netgr_matches(n, h, sh, u) - char *n, *h, *sh, *u; +user_is_exempt() { - return(TRUE); + return(FALSE); } +/* STUB */ void -set_fqdn() +sudo_setspent() { return; } -int -set_runaspw(user) - char *user; -{ - extern int sudolineno, used_runas; - - if (used_runas) { - (void) fprintf(stderr, - "%s: runas_default set after old value is in use near line %d\n", - pedantic > 1 ? "Error" : "Warning", sudolineno); - if (pedantic > 1) - yyerror(NULL); - } - return(TRUE); -} - -int -user_is_exempt() +/* STUB */ +void +sudo_endspent() { - return(TRUE); + return; } -void -init_envtables() +char * +sudo_getepw(pw) + const struct passwd *pw; { - return; + return (pw->pw_passwd); } /* @@ -575,9 +633,10 @@ setup_signals() /* * Setup signal handlers to cleanup nicely. */ + zero_bytes(&sa, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - sa.sa_handler = Exit; + sa.sa_handler = quit; (void) sigaction(SIGTERM, &sa, NULL); (void) sigaction(SIGHUP, &sa, NULL); (void) sigaction(SIGINT, &sa, NULL); @@ -594,14 +653,14 @@ run_command(path, argv) switch (pid = fork()) { case -1: - warn("unable to run %s", path); - Exit(-1); + error(1, "unable to run %s", path); break; /* NOTREACHED */ case 0: - endpwent(); + sudo_endpwent(); + sudo_endgrent(); closefrom(STDERR_FILENO + 1); execv(path, argv); - warn("unable to run %s", path); + warning("unable to run %s", path); _exit(127); break; /* NOTREACHED */ } @@ -620,86 +679,111 @@ run_command(path, argv) } static int -check_syntax() +check_syntax(sudoers_path, quiet, strict) + char *sudoers_path; + int quiet; + int strict; { + struct stat sb; + int error; - if ((yyin = fopen(sudoers.path, "r")) == NULL) { + if ((yyin = fopen(sudoers_path, "r")) == NULL) { if (!quiet) - warn("unable to open %s", sudoers.path); + warning("unable to open %s", sudoers_path); exit(1); } - init_parser(); + init_parser(sudoers_path, quiet); if (yyparse() && parse_error != TRUE) { if (!quiet) - warnx("failed to parse %s file, unknown error", sudoers.path); + warningx("failed to parse %s file, unknown error", sudoers_path); parse_error = TRUE; } - if (!quiet){ + 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", sudoers_path, errorlineno); else - (void) printf("%s file parsed OK\n", sudoers.path); + (void) printf("%s: parsed OK\n", sudoers_path); } - - return(parse_error == TRUE); -} - -static FILE * -open_sudoers(sp) - struct sudoersfile *sp; -{ - struct stat sb; - ssize_t nread; - FILE *fp; - char buf[PATH_MAX*2]; - int tfd; - - /* Open and lock sudoers. */ - sp->fd = open(sp->path, O_RDWR | O_CREAT, SUDOERS_MODE); - if (sp->fd == -1) - err(1, "%s", sp->path); - if (!lock_file(sp->fd, SUDO_TLOCK)) - errx(1, "%s busy, try again later", sp->path); - if ((fp = fdopen(sp->fd, "r")) == NULL) - err(1, "%s", sp->path); - - /* Stash sudoers size and mtime. */ + /* Check mode and owner in strict mode. */ #ifdef HAVE_FSTAT - if (fstat(sp->fd, &sb) == -1) + if (strict && fstat(fileno(yyin), &sb) == 0) #else - if (stat(sp->path, &sb) == -1) + if (strict && stat(sudoers_path, &sb) == 0) #endif - err(1, "can't stat %s", sp->path); - sp->orig_size = sb.st_size; - sp->orig_mtim.tv_sec = mtim_getsec(sb); - sp->orig_mtim.tv_nsec = mtim_getnsec(sb); - - /* Create the temp file. */ - tfd = open(sp->tpath, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (tfd < 0) - err(1, "%s", sp->tpath); + { + if (sb.st_uid != SUDOERS_UID || sb.st_gid != SUDOERS_GID) { + error = TRUE; + if (!quiet) { + fprintf(stderr, "%s: wrong owner (uid, gid) should be (%d, %d)\n", + sudoers_path, SUDOERS_UID, SUDOERS_GID); + } + } + if ((sb.st_mode & 07777) != SUDOERS_MODE) { + error = TRUE; + if (!quiet) { + fprintf(stderr, "%s: bad permissions, should be mode 0%o\n", + sudoers_path, SUDOERS_MODE); + } + } + } - /* Install signal handlers to clean up temp file if we are killed. */ - setup_signals(); + return(error); +} - /* Copy sp->path -> sp->tpath. */ - if (sp->orig_size != 0) { - while ((nread = read(sp->fd, buf, sizeof(buf))) > 0) - if (write(tfd, buf, nread) != nread) { - warn("write error"); - Exit(-1); - } +/* + * Used to open (and lock) the initial sudoers file and to also open + * any subsequent files #included via a callback from the parser. + */ +FILE * +open_sudoers(path, keepopen) + const char *path; + int *keepopen; +{ + struct sudoersfile *entry; + FILE *fp; - /* Add missing newline at EOF if needed. */ - if (nread > 0 && buf[nread - 1] != '\n') { - buf[0] = '\n'; - write(tfd, buf, 1); + /* Check for existing entry */ + tq_foreach_fwd(&sudoerslist, entry) { + if (strcmp(path, entry->path) == 0) + break; + } + if (entry == NULL) { + entry = emalloc(sizeof(*entry)); + entry->path = estrdup(path); + entry->modified = 0; + entry->next = NULL; + entry->fd = open(entry->path, O_RDWR | O_CREAT, SUDOERS_MODE); + entry->tpath = NULL; + if (entry->fd == -1) { + warning("%s", entry->path); + efree(entry); + return(NULL); + } + if (!lock_file(entry->fd, SUDO_TLOCK)) + errorx(1, "%s busy, try again later", entry->path); + if ((fp = fdopen(entry->fd, "r")) == NULL) + error(1, "%s", entry->path); + /* XXX - macro here? */ + if (sudoerslist.last == NULL) + sudoerslist.first = sudoerslist.last = entry; + else { + 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) { + if ((fp = fopen(entry->tpath, "r")) == NULL) + error(1, "%s", entry->tpath); + } else { + if ((fp = fdopen(entry->fd, "r")) == NULL) + error(1, "%s", entry->path); } } - (void) close(tfd); - rewind(fp); - return(fp); } @@ -727,8 +811,7 @@ get_editor(args) } else { if (def_env_editor) { /* If we are honoring $EDITOR this is a fatal error. */ - warnx("specified editor (%s) doesn't exist!", UserEditor); - Exit(-1); + errorx(1, "specified editor (%s) doesn't exist!", UserEditor); } else { /* Otherwise, just ignore $EDITOR. */ UserEditor = NULL; @@ -751,8 +834,7 @@ get_editor(args) if (stat(UserEditor, &user_editor_sb) != 0) { /* Should never happen since we already checked above. */ - warn("unable to stat editor (%s)", UserEditor); - Exit(-1); + error(1, "unable to stat editor (%s)", UserEditor); } EditorPath = estrdup(def_editor); Editor = strtok(EditorPath, ":"); @@ -799,10 +881,8 @@ get_editor(args) } while ((Editor = strtok(NULL, ":"))); /* Bleah, none of the editors existed! */ - if (Editor == NULL || *Editor == '\0') { - warnx("no editor found (editor path = %s)", def_editor); - Exit(-1); - } + if (Editor == NULL || *Editor == '\0') + errorx(1, "no editor found (editor path = %s)", def_editor); } *args = EditorArgs; return(Editor); @@ -829,24 +909,165 @@ get_args(cmnd) } /* - * Unlink the sudoers temp file (if it exists) and exit. - * Used in place of a normal exit() and as a signal handler. - * A positive parameter indicates we were called as a signal handler. + * Iterate through the sudoers datastructures looking for undefined + * aliases or unused aliases. */ -static RETSIGTYPE -Exit(sig) - int sig; +static int +check_aliases(strict) + int strict; { -#define emsg " exiting due to signal.\n" + struct cmndspec *cs; + struct member *m, *binding; + struct privilege *priv; + struct userspec *us; + struct defaults *d; + int atype, error = 0; + + /* 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); + error++; + } + } + } + tq_foreach_fwd(&us->privileges, priv) { + 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); + error++; + } + } + } + tq_foreach_fwd(&priv->cmndlist, cs) { + 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); + 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); + error++; + } + } + } + } + } - (void) unlink(sudoers.tpath); + /* Reverse check (destructive) */ + tq_foreach_fwd(&userspecs, us) { + tq_foreach_fwd(&us->users, m) { + if (m->type == ALIAS) + (void) alias_remove(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); + } + tq_foreach_fwd(&priv->cmndlist, cs) { + tq_foreach_fwd(&cs->runasuserlist, m) { + if (m->type == ALIAS) + (void) alias_remove(m->name, RUNASALIAS); + } + if ((m = cs->cmnd)->type == ALIAS) + (void) alias_remove(m->name, CMNDALIAS); + } + } + } + tq_foreach_fwd(&defaults, d) { + switch (d->type) { + case DEFAULTS_HOST: + atype = HOSTALIAS; + break; + case DEFAULTS_USER: + atype = USERALIAS; + break; + case DEFAULTS_RUNAS: + atype = RUNASALIAS; + break; + case DEFAULTS_CMND: + atype = CMNDALIAS; + break; + default: + continue; /* not an alias */ + } + tq_foreach_fwd(&d->binding, binding) { + for (m = binding; m != NULL; m = m->next) { + if (m->type == ALIAS) + (void) alias_remove(m->name, atype); + } + } + } + + /* If all aliases were referenced we will have an empty tree. */ + if (no_aliases()) + return(0); + alias_apply(print_unused, strict ? "Error" : "Warning"); + return (strict ? 1 : 0); +} + +static int +print_unused(v1, v2) + void *v1; + void *v2; +{ + struct alias *a = (struct alias *)v1; + char *prefix = (char *)v2; + + warningx("%s: unused %s_Alias %s", prefix, + a->type == HOSTALIAS ? "Host" : a->type == CMNDALIAS ? "Cmnd" : + a->type == USERALIAS ? "User" : a->type == RUNASALIAS ? "Runas" : + "Unknown", a->name); + return(0); +} - if (sig > 0) { - write(STDERR_FILENO, getprogname(), strlen(getprogname())); - write(STDERR_FILENO, emsg, sizeof(emsg) - 1); - _exit(sig); +/* + * Unlink any sudoers temp files that remain. + */ +void +cleanup(gotsignal) + int gotsignal; +{ + struct sudoersfile *sp; + + tq_foreach_fwd(&sudoerslist, sp) { + if (sp->tpath != NULL) + (void) unlink(sp->tpath); } - exit(-sig); + if (!gotsignal) { + sudo_endpwent(); + sudo_endgrent(); + } +} + +/* + * Unlink sudoers temp files (if any) and exit. + */ +static RETSIGTYPE +quit(signo) + int signo; +{ + cleanup(signo); +#define emsg " exiting due to signal.\n" + write(STDERR_FILENO, getprogname(), strlen(getprogname())); + write(STDERR_FILENO, emsg, sizeof(emsg) - 1); + _exit(signo); } static void diff --git a/visudo.cat b/visudo.cat index 7eed3c7..74be714 100644 --- a/visudo.cat +++ b/visudo.cat @@ -11,96 +11,91 @@ SSYYNNOOPPSSIISS vviissuuddoo [--cc] [--qq] [--ss] [--VV] [--ff _s_u_d_o_e_r_s] DDEESSCCRRIIPPTTIIOONN - vviissuuddoo edits the _s_u_d_o_e_r_s file in a safe fashion, analogous - to _v_i_p_w(1m). vviissuuddoo locks the _s_u_d_o_e_r_s file against multi­ - ple simultaneous edits, provides basic sanity checks, and - checks for parse errors. If the _s_u_d_o_e_r_s file is currently - being edited you will receive a message to try again - later. - - There is a hard-coded list of editors that vviissuuddoo will use - set at compile-time that may be overridden via the _e_d_i_t_o_r - _s_u_d_o_e_r_s Default variable. This list defaults to the path - to _v_i(1) on your system, as determined by the _c_o_n_f_i_g_u_r_e - script. Normally, vviissuuddoo does not honor the VISUAL or - EDITOR environment variables unless they contain an editor - in the aforementioned editors list. However, if vviissuuddoo is - configured with the _-_-_w_i_t_h_-_e_n_v_e_d_i_t_o_r flag or the _e_n_v___e_d_i_­ - _t_o_r Default variable is set in _s_u_d_o_e_r_s, vviissuuddoo will use - any the editor defines by VISUAL or EDITOR. Note that - this can be a security hole since it allows the user to - execute any program they wish simply by setting VISUAL or - EDITOR. - - vviissuuddoo parses the _s_u_d_o_e_r_s file after the edit and will not - save the changes if there is a syntax error. Upon finding - an error, vviissuuddoo will print a message stating the line - number(s) where the error occurred and the user will - receive the "What now?" prompt. At this point the user - may enter "e" to re-edit the _s_u_d_o_e_r_s file, "x" to exit - without saving the changes, or "Q" to quit and save - changes. The "Q" option should be used with extreme care - because if vviissuuddoo believes there to be a parse error, so - will ssuuddoo and no one will be able to ssuuddoo again until the - error is fixed. If "e" is typed to edit the _s_u_d_o_e_r_s file - after a parse error has been detected, the cursor will be - placed on the line where the error occurred (if the editor - supports this feature). + vviissuuddoo edits the _s_u_d_o_e_r_s file in a safe fashion, analogous to _v_i_p_w(1m). + vviissuuddoo locks the _s_u_d_o_e_r_s file against multiple simultaneous edits, + provides basic sanity checks, and checks for parse errors. If the + _s_u_d_o_e_r_s file is currently being edited you will receive a message to + try again later. + + There is a hard-coded list of editors that vviissuuddoo will use set at + compile-time that may be overridden via the _e_d_i_t_o_r _s_u_d_o_e_r_s Default + variable. This list defaults to the path to _v_i(1) on your system, as + determined by the _c_o_n_f_i_g_u_r_e script. Normally, vviissuuddoo does not honor + the VISUAL or EDITOR environment variables unless they contain an + editor in the aforementioned editors list. However, if vviissuuddoo is + configured with the _-_-_w_i_t_h_-_e_n_v_e_d_i_t_o_r option or the _e_n_v___e_d_i_t_o_r Default + variable is set in _s_u_d_o_e_r_s, vviissuuddoo will use any the editor defines by + VISUAL or EDITOR. Note that this can be a security hole since it + allows the user to execute any program they wish simply by setting + VISUAL or EDITOR. + + vviissuuddoo parses the _s_u_d_o_e_r_s file after the edit and will not save the + changes if there is a syntax error. Upon finding an error, vviissuuddoo will + print a message stating the line number(s) where the error occurred and + the user will receive the "What now?" prompt. At this point the user + may enter "e" to re-edit the _s_u_d_o_e_r_s file, "x" to exit without saving + the changes, or "Q" to quit and save changes. The "Q" option should be + used with extreme care because if vviissuuddoo believes there to be a parse + error, so will ssuuddoo and no one will be able to ssuuddoo again until the + error is fixed. If "e" is typed to edit the _s_u_d_o_e_r_s file after a + parse error has been detected, the cursor will be placed on the line + where the error occurred (if the editor supports this feature). OOPPTTIIOONNSS vviissuuddoo accepts the following command line options: - -c Enable cchheecckk--oonnllyy mode. The existing _s_u_d_o_e_r_s file - will be checked for syntax and a message will be - printed to the standard output detailing the status of - _s_u_d_o_e_r_s. If the syntax check completes successfully, - vviissuuddoo will exit with a value of 0. If a syntax error - is encountered, vviissuuddoo will exit with a value of 1. + -c Enable cchheecckk--oonnllyy mode. The existing _s_u_d_o_e_r_s file will be + checked for syntax and a message will be printed to the + standard output detailing the status of _s_u_d_o_e_r_s. If the + syntax check completes successfully, vviissuuddoo will exit with + a value of 0. If a syntax error is encountered, vviissuuddoo + will exit with a value of 1. - -f Specify and alternate _s_u_d_o_e_r_s file location. With + -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" + appended to it. + -q Enable qquuiieett mode. In this mode details about syntax -1.6.9p17 Jun 21, 2008 1 +1.7.0 November 15, 2008 1 -VISUDO(1m) MAINTENANCE COMMANDS VISUDO(1m) +VISUDO(1m) MAINTENANCE COMMANDS VISUDO(1m) - this option vviissuuddoo will edit (or check) the _s_u_d_o_e_r_s - file of your 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 - errors are not printed. This option is only useful - when combined with the --cc flag. + errors are not printed. This option is only useful when + combined with the --cc option. - -s Enable ssttrriicctt checking of the _s_u_d_o_e_r_s file. If an - alias is used before it is defined, vviissuuddoo will con­ - sider this a parse error. Note that it is not possi­ - ble to differentiate between an alias and a hostname - or username that consists solely of uppercase letters, - digits, and the underscore ('_') character. + -s Enable ssttrriicctt checking of the _s_u_d_o_e_r_s file. If an alias is + used before it is defined, vviissuuddoo will consider this a + parse error. Note that it is not possible to differentiate + between an alias and a hostname or username that consists + solely of uppercase letters, digits, and the underscore + ('_') character. - -V The --VV (version) option causes vviissuuddoo to print its - version number and exit. + -V The --VV (version) option causes vviissuuddoo to print its version + number and exit. EENNVVIIRROONNMMEENNTT - The following environment variables are used only if - vviissuuddoo was configured with the _-_-_w_i_t_h_-_e_n_v_-_e_d_i_t_o_r option: + The following environment variables may be consulted depending on the + value of the _e_d_i_t_o_r and _e_n_v___e_d_i_t_o_r _s_u_d_o_e_r_s variables: VISUAL Invoked by visudo as the editor to use EDITOR Used by visudo if VISUAL is not set FFIILLEESS - _/_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 List of who can run what - _/_e_t_c_/_s_u_d_o_e_r_s_._t_m_p Lock file for visudo + _@_s_y_s_c_o_n_f_d_i_r_@_/_s_u_d_o_e_r_s_._t_m_p + Lock file for visudo DDIIAAGGNNOOSSTTIICCSS sudoers file busy, try again later. @@ -112,45 +107,38 @@ DDIIAAGGNNOOSSTTIICCSS Can't find you in the passwd database Your userid does not appear in the system passwd file. - Warning: undeclared Alias referenced near ... - Either you are using a {User,Runas,Host,Cmnd}_Alias - before defining it or you have a user or hostname - listed that consists solely of uppercase letters, dig­ - its, and the underscore ('_') character. If the lat­ - ter, you can ignore the warnings (ssuuddoo will not com­ - plain). In --ss (strict) mode these are errors, not - warnings. + Warning: {User,Runas,Host,Cmnd}_Alias referenced but not defined + Either you are trying to use an undeclare + {User,Runas,Host,Cmnd}_Alias or you have a user or hostname listed + that consists solely of uppercase letters, digits, and the + underscore ('_') character. In the latter case, you can ignore the + warnings (ssuuddoo will not complain). In --ss (strict) mode these are + errors, not warnings. - Warning: runas_default set after old value is in use ... - You have a _r_u_n_a_s___d_e_f_a_u_l_t Defaults setting listed in - the _s_u_d_o_e_r_s file after its value has already been + Warning: unused {User,Runas,Host,Cmnd}_Alias + The specified {User,Runas,Host,Cmnd}_Alias was defined but never + used. You may wish to comment out or remove the unused alias. In + --ss (strict) mode this is an error, not a warning. +SSEEEE AALLSSOO + _v_i(1), _s_u_d_o_e_r_s(4), _s_u_d_o(1m), _v_i_p_w(8) -1.6.9p17 Jun 21, 2008 2 +1.7.0 November 15, 2008 2 -VISUDO(1m) MAINTENANCE COMMANDS VISUDO(1m) - used. This means that entries prior to the - _r_u_n_a_s___d_e_f_a_u_l_t setting will match based on the default - value of _r_u_n_a_s___d_e_f_a_u_l_t (root) whereas entries aafftteerr - the _r_u_n_a_s___d_e_f_a_u_l_t setting will match based on the new - value. This is usually unintentional and in most - cases the setting should be placed - before any Runas_Alias or User specifications. In --ss - (strict) mode this is an error, not a warning. -SSEEEE AALLSSOO - _v_i(1), _s_u_d_o_e_r_s(4), _s_u_d_o(1m), _v_i_p_w(8) +VISUDO(1m) MAINTENANCE COMMANDS VISUDO(1m) + AAUUTTHHOORR - Many people have worked on _s_u_d_o over the years; this ver­ - sion of vviissuuddoo was written by: + Many people have worked on _s_u_d_o over the years; this version of vviissuuddoo + was written by: Todd Miller @@ -158,26 +146,38 @@ AAUUTTHHOORR http://www.sudo.ws/sudo/history.html for more details. CCAAVVEEAATTSS - There is no easy way to prevent a user from gaining a root - shell if the editor used by vviissuuddoo allows shell escapes. + There is no easy way to prevent a user from gaining a root shell if the + editor used by vviissuuddoo allows shell escapes. BBUUGGSS - If you feel you have found a bug in vviissuuddoo, please submit - a bug report at http://www.sudo.ws/sudo/bugs/ + If you feel you have found a bug in vviissuuddoo, please submit a bug report + at http://www.sudo.ws/sudo/bugs/ SSUUPPPPOORRTT - Limited free support is available via the sudo-users mail­ - ing list, see http://www.sudo.ws/mail­ - man/listinfo/sudo-users to subscribe or search the - archives. + Limited free support is available via the sudo-users mailing list, see + http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search + the archives. DDIISSCCLLAAIIMMEERR - vviissuuddoo is provided ``AS IS'' and any express or implied - warranties, including, but not limited to, the implied - warranties of merchantability and fitness for a particular - purpose are disclaimed. See the LICENSE file distributed - with ssuuddoo or http://www.sudo.ws/sudo/license.html for com­ - plete details. + vviissuuddoo is provided ``AS IS'' and any express or implied warranties, + including, but not limited to, the implied warranties of + merchantability and fitness for a particular purpose are disclaimed. + See the LICENSE file distributed with ssuuddoo or + http://www.sudo.ws/sudo/license.html for complete details. + + + + + + + + + + + + + + @@ -193,6 +193,6 @@ DDIISSCCLLAAIIMMEERR -1.6.9p17 Jun 21, 2008 3 +1.7.0 November 15, 2008 3 diff --git a/visudo.man.in b/visudo.man.in index 87ca8ab..7aa576b 100644 --- a/visudo.man.in +++ b/visudo.man.in @@ -1,4 +1,5 @@ -.\" Copyright (c) 1996,1998-2005, 2007 Todd C. Miller +.\" Copyright (c) 1996,1998-2005, 2007-2008 +.\" 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 @@ -17,8 +18,8 @@ .\" 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.20.2.22 2008/06/22 20:29:03 millert Exp $ -.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 +.\" $Sudo: visudo.man.in,v 1.32 2008/11/15 18:34:26 millert Exp $ +.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.05) .\" .\" Standard preamble: .\" ======================================================================== @@ -45,11 +46,11 @@ .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. | will give a -.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to -.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' -.\" expand to `' in nroff, nothing in troff, for use with C<>. -.tr \(*W-|\(bv\*(Tr +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- @@ -68,22 +69,25 @@ . ds R" '' 'br\} .\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. -.if \nF \{\ +.ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} -.\" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.hy 0 -.if n .na +.el \{\ +. de IX +.. +.\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. @@ -149,7 +153,11 @@ .\" ======================================================================== .\" .IX Title "VISUDO @mansectsu@" -.TH VISUDO @mansectsu@ "Jun 21, 2008" "1.6.9p17" "MAINTENANCE COMMANDS" +.TH VISUDO @mansectsu@ "November 15, 2008" "1.7.0" "MAINTENANCE COMMANDS" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh .SH "NAME" visudo \- edit the sudoers file .SH "SYNOPSIS" @@ -170,7 +178,7 @@ your system, as determined by the \fIconfigure\fR script. Normally, \&\fBvisudo\fR does not honor the \f(CW\*(C`VISUAL\*(C'\fR or \f(CW\*(C`EDITOR\*(C'\fR environment variables unless they contain an editor in the aforementioned editors list. However, if \fBvisudo\fR is configured with the \fI\-\-with\-enveditor\fR -flag or the \fIenv_editor\fR \f(CW\*(C`Default\*(C'\fR variable is set in \fIsudoers\fR, +option or the \fIenv_editor\fR \f(CW\*(C`Default\*(C'\fR variable is set in \fIsudoers\fR, \&\fBvisudo\fR will use any the editor defines by \f(CW\*(C`VISUAL\*(C'\fR or \f(CW\*(C`EDITOR\*(C'\fR. Note that this can be a security hole since it allows the user to execute any program they wish simply by setting \f(CW\*(C`VISUAL\*(C'\fR or \f(CW\*(C`EDITOR\*(C'\fR. @@ -191,7 +199,7 @@ error occurred (if the editor supports this feature). .SH "OPTIONS" .IX Header "OPTIONS" \&\fBvisudo\fR accepts the following command line options: -.IP "\-c" 4 +.IP "\-c" 12 .IX Item "-c" Enable \fBcheck-only\fR mode. The existing \fIsudoers\fR file will be checked for syntax and a message will be printed to the @@ -199,32 +207,32 @@ standard output detailing the status of \fIsudoers\fR. If the syntax check completes successfully, \fBvisudo\fR will exit with a value of 0. If a syntax error is encountered, \&\fBvisudo\fR will exit with a value of 1. -.IP "\-f" 4 -.IX Item "-f" +.IP "\-f \fIsudoers\fR" 12 +.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@sysconfdir@/sudoers\fR. The lock file used +instead of the default, \fI\f(CI@sysconfdir\fI@/sudoers\fR. The lock file used is the specified \fIsudoers\fR file with \*(L".tmp\*(R" appended to it. -.IP "\-q" 4 +.IP "\-q" 12 .IX Item "-q" Enable \fBquiet\fR mode. In this mode details about syntax errors are not printed. This option is only useful when combined with -the \fB\-c\fR flag. -.IP "\-s" 4 +the \fB\-c\fR option. +.IP "\-s" 12 .IX Item "-s" Enable \fBstrict\fR checking of the \fIsudoers\fR file. If an alias is used before it is defined, \fBvisudo\fR will consider this a parse error. Note that it is not possible to differentiate between an alias and a hostname or username that consists solely of uppercase letters, digits, and the underscore ('_') character. -.IP "\-V" 4 +.IP "\-V" 12 .IX Item "-V" The \fB\-V\fR (version) option causes \fBvisudo\fR to print its version number and exit. .SH "ENVIRONMENT" .IX Header "ENVIRONMENT" -The following environment variables are used only if \fBvisudo\fR -was configured with the \fI\-\-with\-env\-editor\fR option: +The following environment variables may be consulted depending on +the value of the \fIeditor\fR and \fIenv_editor\fR \fIsudoers\fR variables: .ie n .IP "\*(C`VISUAL\*(C'" 16 .el .IP "\f(CW\*(C`VISUAL\*(C'\fR" 16 .IX Item "VISUAL" @@ -235,10 +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" -.IP "\fI@sysconfdir@/sudoers\fR" 24 +.ie n .IP "\fI\fI@sysconfdir\fI@/sudoers\fR" 24 +.el .IP "\fI\f(CI@sysconfdir\fI@/sudoers\fR" 24 .IX Item "@sysconfdir@/sudoers" List of who can run what -.IP "\fI@sysconfdir@/sudoers.tmp\fR" 24 +.ie n .IP "\fI\fI@sysconfdir\fI@/sudoers.tmp\fR" 24 +.el .IP "\fI\f(CI@sysconfdir\fI@/sudoers.tmp\fR" 24 .IX Item "@sysconfdir@/sudoers.tmp" Lock file for visudo .SH "DIAGNOSTICS" @@ -246,31 +256,25 @@ Lock file for visudo .IP "sudoers file busy, try again later." 4 .IX Item "sudoers file busy, try again later." Someone else is currently editing the \fIsudoers\fR file. -.IP "@sysconfdir@/sudoers.tmp: Permission denied" 4 +.ie n .IP "@sysconfdir@/sudoers.tmp: Permission denied" 4 +.el .IP "\f(CW@sysconfdir\fR@/sudoers.tmp: Permission denied" 4 .IX Item "@sysconfdir@/sudoers.tmp: Permission denied" You didn't run \fBvisudo\fR as root. .IP "Can't find you in the passwd database" 4 .IX Item "Can't find you in the passwd database" Your userid does not appear in the system passwd file. -.IP "Warning: undeclared Alias referenced near ..." 4 -.IX Item "Warning: undeclared Alias referenced near ..." -Either you are using a {User,Runas,Host,Cmnd}_Alias before -defining it or you have a user or hostname listed that -consists solely of uppercase letters, digits, and the -underscore ('_') character. If the latter, you can ignore -the warnings (\fBsudo\fR will not complain). In \fB\-s\fR (strict) -mode these are errors, not warnings. -.IP "Warning: runas_default set after old value is in use ..." 4 -.IX Item "Warning: runas_default set after old value is in use ..." -You have a \fIrunas_default\fR Defaults setting listed in the \fIsudoers\fR -file after its value has already been used. This means that entries -prior to the \fIrunas_default\fR setting will match based on the default -value of \fIrunas_default\fR (\f(CW\*(C`@runas_default@\*(C'\fR) whereas entries -\&\fBafter\fR the \fIrunas_default\fR setting will match based on the new -value. This is usually unintentional and in most cases the - setting should be placed before any \f(CW\*(C`Runas_Alias\*(C'\fR -or User specifications. In \fB\-s\fR (strict) mode this is an error, -not a warning. +.IP "Warning: {User,Runas,Host,Cmnd}_Alias referenced but not defined" 4 +.IX Item "Warning: {User,Runas,Host,Cmnd}_Alias referenced but not defined" +Either you are trying to use an undeclare {User,Runas,Host,Cmnd}_Alias +or you have a user or hostname listed that consists solely of +uppercase letters, digits, and the underscore ('_') character. In +the latter case, you can ignore the warnings (\fBsudo\fR will not +complain). In \fB\-s\fR (strict) mode these are errors, not warnings. +.IP "Warning: unused {User,Runas,Host,Cmnd}_Alias" 4 +.IX Item "Warning: unused {User,Runas,Host,Cmnd}_Alias" +The specified {User,Runas,Host,Cmnd}_Alias was defined but never +used. You may wish to comment out or remove the unused alias. In +\&\fB\-s\fR (strict) mode this is an error, not a warning. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fIvi\fR\|(1), \fIsudoers\fR\|(@mansectform@), \fIsudo\fR\|(@mansectsu@), \fIvipw\fR\|(8) diff --git a/visudo.pod b/visudo.pod index d914fab..63cb113 100644 --- a/visudo.pod +++ b/visudo.pod @@ -1,4 +1,5 @@ -Copyright (c) 1996,1998-2005, 2007 Todd C. Miller +Copyright (c) 1996,1998-2005, 2007-2008 + 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 @@ -17,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: visudo.pod,v 1.38.2.10 2008/02/19 15:45:12 millert Exp $ +$Sudo: visudo.pod,v 1.55 2008/11/15 18:34:01 millert Exp $ =pod =head1 NAME @@ -43,7 +44,7 @@ your system, as determined by the I script. Normally, B does not honor the C or C environment variables unless they contain an editor in the aforementioned editors list. However, if B is configured with the I<--with-enveditor> -flag or the I C variable is set in I, +option or the I C variable is set in I, B will use any the editor defines by C or C. Note that this can be a security hole since it allows the user to execute any program they wish simply by setting C or C. @@ -66,7 +67,7 @@ error occurred (if the editor supports this feature). B accepts the following command line options: -=over 4 +=over 12 =item -c @@ -77,7 +78,7 @@ If the syntax check completes successfully, B will exit with a value of 0. If a syntax error is encountered, B will exit with a value of 1. -=item -f +=item -f I Specify and alternate I file location. With this option B will edit (or check) the I file of your choice, @@ -88,7 +89,7 @@ is the specified I file with ".tmp" appended to it. Enable B mode. In this mode details about syntax errors are not printed. This option is only useful when combined with -the B<-c> flag. +the B<-c> option. =item -s @@ -107,8 +108,8 @@ and exit. =head1 ENVIRONMENT -The following environment variables are used only if B -was configured with the I<--with-env-editor> option: +The following environment variables may be consulted depending on +the value of the I and I I variables: =over 16 @@ -152,26 +153,19 @@ You didn't run B as root. Your userid does not appear in the system passwd file. -=item Warning: undeclared Alias referenced near ... - -Either you are using a {User,Runas,Host,Cmnd}_Alias before -defining it or you have a user or hostname listed that -consists solely of uppercase letters, digits, and the -underscore ('_') character. If the latter, you can ignore -the warnings (B will not complain). In B<-s> (strict) -mode these are errors, not warnings. - -=item Warning: runas_default set after old value is in use ... - -You have a I Defaults setting listed in the I -file after its value has already been used. This means that entries -prior to the I setting will match based on the default -value of I (C<@runas_default@>) whereas entries -B the I setting will match based on the new -value. This is usually unintentional and in most cases the - setting should be placed before any C -or User specifications. In B<-s> (strict) mode this is an error, -not a warning. +=item Warning: {User,Runas,Host,Cmnd}_Alias referenced but not defined + +Either you are trying to use an undeclare {User,Runas,Host,Cmnd}_Alias +or you have a user or hostname listed that consists solely of +uppercase letters, digits, and the underscore ('_') character. In +the latter case, you can ignore the warnings (B will not +complain). In B<-s> (strict) mode these are errors, not warnings. + +=item Warning: unused {User,Runas,Host,Cmnd}_Alias + +The specified {User,Runas,Host,Cmnd}_Alias was defined but never +used. You may wish to comment out or remove the unused alias. In +B<-s> (strict) mode this is an error, not a warning. =back diff --git a/zero_bytes.c b/zero_bytes.c index f77c8cf..8ce2eb5 100644 --- a/zero_bytes.c +++ b/zero_bytes.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2005 Todd C. Miller + * Copyright (c) 2003-2005, 2007 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 @@ -20,7 +20,7 @@ #include #ifndef lint -__unused static const char rcsid[] = "$Sudo: zero_bytes.c,v 1.2.2.2 2007/06/12 01:28:42 millert Exp $"; +__unused static const char rcsid[] = "$Sudo: zero_bytes.c,v 1.7 2008/11/09 14:13:12 millert Exp $"; #endif /* lint */ /* @@ -29,7 +29,7 @@ __unused static const char rcsid[] = "$Sudo: zero_bytes.c,v 1.2.2.2 2007/06/12 0 */ void zero_bytes(v, n) - volatile VOID *v; + volatile void *v; size_t n; { volatile char *p, *ep;