summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>1996-10-14 05:14:59 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>1996-10-14 05:14:59 +0000
commit4403da4c4135881add7d2a5b81282fbcb01ae47c (patch)
tree55ab58992d6e1d1b00c327d278ec2f1b9947d6fb /gnu
parent0a64da4f22aa6e7dc9ce23604386381860186ad4 (diff)
sudo 1.5.2
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/sudo/COPYING339
-rw-r--r--gnu/usr.bin/sudo/Makefile5
-rw-r--r--gnu/usr.bin/sudo/README3
-rw-r--r--gnu/usr.bin/sudo/sudo/Makefile41
-rw-r--r--gnu/usr.bin/sudo/sudo/check.c860
-rw-r--r--gnu/usr.bin/sudo/sudo/compat.h145
-rw-r--r--gnu/usr.bin/sudo/sudo/config.h304
-rw-r--r--gnu/usr.bin/sudo/sudo/find_path.c187
-rw-r--r--gnu/usr.bin/sudo/sudo/getspwuid.c266
-rw-r--r--gnu/usr.bin/sudo/sudo/goodpath.c99
-rw-r--r--gnu/usr.bin/sudo/sudo/ins_2001.h39
-rw-r--r--gnu/usr.bin/sudo/sudo/ins_classic.h39
-rw-r--r--gnu/usr.bin/sudo/sudo/ins_csops.h40
-rw-r--r--gnu/usr.bin/sudo/sudo/ins_goons.h54
-rw-r--r--gnu/usr.bin/sudo/sudo/insults.h71
-rw-r--r--gnu/usr.bin/sudo/sudo/interfaces.c264
-rw-r--r--gnu/usr.bin/sudo/sudo/logging.c709
-rw-r--r--gnu/usr.bin/sudo/sudo/options.h110
-rw-r--r--gnu/usr.bin/sudo/sudo/parse.c446
-rw-r--r--gnu/usr.bin/sudo/sudo/parse.lex354
-rw-r--r--gnu/usr.bin/sudo/sudo/parse.yacc954
-rw-r--r--gnu/usr.bin/sudo/sudo/pathnames.h90
-rw-r--r--gnu/usr.bin/sudo/sudo/sudo.8378
-rw-r--r--gnu/usr.bin/sudo/sudo/sudo.c999
-rw-r--r--gnu/usr.bin/sudo/sudo/sudo.h236
-rw-r--r--gnu/usr.bin/sudo/sudo/sudo_setenv.c94
-rw-r--r--gnu/usr.bin/sudo/sudo/sudoers.5435
-rw-r--r--gnu/usr.bin/sudo/sudo/tgetpass.c275
-rw-r--r--gnu/usr.bin/sudo/sudo/version.h28
-rw-r--r--gnu/usr.bin/sudo/visudo/Makefile23
-rw-r--r--gnu/usr.bin/sudo/visudo/visudo.8266
-rw-r--r--gnu/usr.bin/sudo/visudo/visudo.c512
32 files changed, 8665 insertions, 0 deletions
diff --git a/gnu/usr.bin/sudo/COPYING b/gnu/usr.bin/sudo/COPYING
new file mode 100644
index 00000000000..a43ea2126fb
--- /dev/null
+++ b/gnu/usr.bin/sudo/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/usr.bin/sudo/Makefile b/gnu/usr.bin/sudo/Makefile
new file mode 100644
index 00000000000..7b76abe73aa
--- /dev/null
+++ b/gnu/usr.bin/sudo/Makefile
@@ -0,0 +1,5 @@
+# $OpenBSD: Makefile,v 1.1 1996/10/14 05:14:41 millert Exp $
+
+SUBDIR+=sudo visudo
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/sudo/README b/gnu/usr.bin/sudo/README
new file mode 100644
index 00000000000..c73e4fbce4b
--- /dev/null
+++ b/gnu/usr.bin/sudo/README
@@ -0,0 +1,3 @@
+This is a minimal sudo distribution for OpenBSD. You can get the
+full package at ftp://ftp.courtesan.com/pub/sudo/. For info on
+sudo please see http://www.courtesan.com/courtesan/products/sudo/.
diff --git a/gnu/usr.bin/sudo/sudo/Makefile b/gnu/usr.bin/sudo/sudo/Makefile
new file mode 100644
index 00000000000..4770a031d76
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/Makefile
@@ -0,0 +1,41 @@
+# $OpenBSD: Makefile,v 1.1 1996/10/14 05:14:43 millert Exp $
+
+PROG= sudo
+MAN= sudo.8 sudoers.5
+CFLAGS+=-I${.CURDIR} -I.
+SRCS= check.c find_path.c getspwuid.c goodpath.c interfaces.c logging.c parse.c sudo.c sudo_setenv.c tgetpass.c y.tab.c lex.yy.c
+CLEANFILES+=y.tab.c y.tab.h lex.yy.c
+
+LDADD= -lcompat
+DPADD= ${LIBCOMPAT}
+
+.include <bsd.own.mk> # For SKEY, KERBEROS and KERBEROS5
+
+.if defined(SKEY)
+CFLAGS+=-DHAVE_SKEY
+LDADD+= -lskey
+DPADD+= ${LIBSKEY}
+.endif
+
+.if defined(KERBEROS5)
+CFLAGS+= -DHAVE_KERB5
+LDADD+= -lkrb5 -lcrypto
+DPADD+= ${LIBKRB5} ${LIBCRYPTO}
+.elif defined(KERBEROS)
+CFLAGS+= -DHAVE_KERB4
+LDADD+= -lkrb -ldes
+DPADD+= ${LIBKRB} ${LIBDES}
+.endif
+
+BINOWN= root
+BINMODE=4111
+BINDIR?=/usr/bin
+
+.include <bsd.prog.mk>
+
+lex.yy.c: parse.lex
+ rm -f lex.yy.c
+ $(LEX) ${.CURDIR}/parse.lex
+
+y.tab.c y.tab.h: parse.yacc
+ $(YACC) -d ${.CURDIR}/parse.yacc
diff --git a/gnu/usr.bin/sudo/sudo/check.c b/gnu/usr.bin/sudo/sudo/check.c
new file mode 100644
index 00000000000..3c6373252f5
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/check.c
@@ -0,0 +1,860 @@
+/*
+ * CU sudo version 1.5.2 (based on Root Group sudo version 1.1)
+ *
+ * This software comes with no waranty whatsoever, use at your own risk.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ */
+
+/*
+ * sudo version 1.1 allows users to execute commands as root
+ * Copyright (C) 1991 The Root Group, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *******************************************************************
+ *
+ * check.c
+ *
+ * check_user() only returns if the user's timestamp file
+ * is current or if they enter a correct password.
+ *
+ * Jeff Nieusma Thu Mar 21 22:39:07 MST 1991
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: check.c,v 1.1 1996/10/14 05:14:43 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <fcntl.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <pwd.h>
+#include <grp.h>
+#include "sudo.h"
+#include <options.h>
+#include "insults.h"
+#if (SHADOW_TYPE == SPW_SECUREWARE)
+# ifdef __hpux
+# include <hpsecurity.h>
+# else
+# include <sys/security.h>
+# endif /* __hpux */
+# include <prot.h>
+#endif /* SPW_SECUREWARE */
+#ifdef HAVE_KERB4
+# include <krb.h>
+#endif /* HAVE_KERB4 */
+#ifdef HAVE_AFS
+# include <afs/stds.h>
+# include <afs/kautils.h>
+#endif /* HAVE_AFS */
+#ifdef HAVE_SECURID
+# include <sdi_athd.h>
+# include <sdconf.h>
+# include <sdacmvls.h>
+#endif /* HAVE_SECURID */
+#ifdef HAVE_SKEY
+# include <skey.h>
+#endif /* HAVE_SKEY */
+#ifdef HAVE_OPIE
+# include <opie.h>
+#endif /* HAVE_OPIE */
+#ifdef HAVE_UTIME
+# ifdef HAVE_UTIME_H
+# include <utime.h>
+# endif /* HAVE_UTIME_H */
+#else
+# include "emul/utime.h"
+#endif /* HAVE_UTIME */
+
+
+/*
+ * Prototypes for local functions
+ */
+static int check_timestamp __P((void));
+static void check_passwd __P((void));
+static int touch __P((char *));
+static void update_timestamp __P((void));
+static void reminder __P((void));
+#ifdef HAVE_KERB4
+static int sudo_krb_validate_user __P((struct passwd *, char *));
+#endif /* HAVE_KERB4 */
+#ifdef HAVE_SKEY
+static char *sudo_skeyprompt __P((struct skey *, char *));
+#endif /* HAVE_SKEY */
+#ifdef HAVE_OPIE
+static char *sudo_opieprompt __P((struct opie *, char *));
+#endif /* HAVE_OPIE */
+int user_is_exempt __P((void));
+
+/*
+ * Globals
+ */
+static int timedir_is_good;
+static char timestampfile[MAXPATHLEN + 1];
+#ifdef HAVE_SECURID
+union config_record configure;
+#endif /* HAVE_SECURID */
+#ifdef HAVE_SKEY
+struct skey skey;
+#endif
+#ifdef HAVE_OPIE
+struct opie opie;
+#endif
+#if (SHADOW_TYPE == SPW_SECUREWARE) && defined(__alpha)
+extern uchar_t crypt_type;
+#endif /* SPW_SECUREWARE && __alpha */
+
+
+
+/********************************************************************
+ *
+ * check_user()
+ *
+ * This function only returns if the user can successfully
+ * verify who s/he is.
+ */
+
+void check_user()
+{
+ register int rtn;
+ mode_t oldmask;
+
+ if (user_is_exempt()) /* some users don't need to enter a passwd */
+ return;
+
+ oldmask = umask(077); /* make sure the timestamp files are private */
+
+ rtn = check_timestamp();
+ if (rtn && user_uid) { /* if timestamp is not current... */
+#ifndef NO_MESSAGE
+ if (rtn == 2)
+ reminder(); /* do the reminder if ticket file is new */
+#endif /* NO_MESSAGE */
+ check_passwd();
+ }
+
+ update_timestamp();
+ (void) umask(oldmask); /* want a real umask to exec() the command */
+
+}
+
+
+
+/********************************************************************
+ *
+ * user_is_exempt()
+ *
+ * this function checks the user is exempt from supplying a password.
+ */
+
+int user_is_exempt()
+{
+#ifdef EXEMPTGROUP
+ struct group *grp;
+ char **gr_mem;
+
+ if ((grp = getgrnam(EXEMPTGROUP)) == NULL)
+ return(FALSE);
+
+ if (getgid() == grp->gr_gid)
+ return(TRUE);
+
+ for (gr_mem = grp->gr_mem; *gr_mem; gr_mem++) {
+ if (strcmp(user_name, *gr_mem) == 0)
+ return(TRUE);
+ }
+
+ return(FALSE);
+#else
+ return(FALSE);
+#endif
+}
+
+
+
+/********************************************************************
+ *
+ * check_timestamp()
+ *
+ * this function checks the timestamp file. If it is within
+ * TIMEOUT minutes, no password will be required
+ */
+
+static int check_timestamp()
+{
+ register char *p;
+ struct stat statbuf;
+ register int timestamp_is_old = -1;
+ time_t now;
+
+#ifdef USE_TTY_TICKETS
+ if (p = strrchr(tty, '/'))
+ p++;
+ else
+ p = tty;
+
+ (void) sprintf(timestampfile, "%s/%s.%s", _PATH_SUDO_TIMEDIR, user_name, p);
+#else
+ (void) sprintf(timestampfile, "%s/%s", _PATH_SUDO_TIMEDIR, user_name);
+#endif /* USE_TTY_TICKETS */
+
+ timedir_is_good = 1; /* now there's an assumption for ya... */
+
+ /* become root */
+ set_perms(PERM_ROOT, 0);
+
+ /*
+ * walk through the path one directory at a time
+ */
+ for (p = timestampfile + 1; (p = strchr(p, '/')); *p++ = '/') {
+ *p = '\0';
+ if (stat(timestampfile, &statbuf) < 0) {
+ if (strcmp(timestampfile, _PATH_SUDO_TIMEDIR))
+ (void) fprintf(stderr, "Cannot stat() %s\n", timestampfile);
+ timedir_is_good = 0;
+ *p = '/';
+ break;
+ }
+ }
+
+ /*
+ * if all the directories are stat()able
+ */
+ if (timedir_is_good) {
+ /*
+ * last component in _PATH_SUDO_TIMEDIR must be owned by root
+ * and mode 0700 or we ignore the timestamps in it.
+ */
+ if (statbuf.st_uid != 0 || (statbuf.st_mode & 0000077)) {
+ timedir_is_good = 0;
+ timestamp_is_old = 2;
+ log_error(BAD_STAMPDIR);
+ inform_user(BAD_STAMPDIR);
+ } else if (stat(timestampfile, &statbuf)) {
+ /* timestamp file does not exist? */
+ timestamp_is_old = 2; /* return (2) */
+ } else {
+ /* check the time against the timestamp file */
+ now = time((time_t *) NULL);
+ if (TIMEOUT && now - statbuf.st_mtime < 60 * TIMEOUT)
+ /* check for bogus time on the stampfile */
+ if (statbuf.st_mtime > now + 60 * TIMEOUT * 2) {
+ timestamp_is_old = 2; /* bogus time value */
+ log_error(BAD_STAMPFILE);
+ inform_user(BAD_STAMPFILE);
+ } else {
+ timestamp_is_old = 0; /* time value is reasonable */
+ }
+ else
+ timestamp_is_old = 1; /* else make 'em enter password */
+ }
+ }
+ /*
+ * there was a problem stat()ing a directory
+ */
+ else {
+ timestamp_is_old = 2; /* user has to enter password + reminder */
+ /* make the TIMEDIR directory */
+ if (mkdir(_PATH_SUDO_TIMEDIR, S_IRWXU)) {
+ perror("check_timestamp: mkdir");
+ timedir_is_good = 0;
+ } else {
+ timedir_is_good = 1; /* _PATH_SUDO_TIMEDIR now exists */
+ }
+ }
+
+ /* relinquish root */
+ set_perms(PERM_USER, 0);
+
+ return (timestamp_is_old);
+}
+
+
+
+/********************************************************************
+ *
+ * touch()
+ *
+ * This function updates the access and modify times on a file
+ * via utime(2).
+ */
+
+static int touch(file)
+ char *file;
+{
+#if defined(HAVE_UTIME) && !defined(HAVE_UTIME_NULL)
+#ifdef HAVE_UTIME_POSIX
+#define UTP (&ut)
+ struct utimbuf ut;
+
+ ut.actime = ut.modtime = time(NULL);
+#else
+#define UTP (ut)
+ /* old BSD <= 4.3 has no struct utimbuf */
+ time_t ut[2];
+
+ ut[0] = ut[1] = time(NULL);
+#endif /* HAVE_UTIME_POSIX */
+#else
+#define UTP NULL
+#endif /* HAVE_UTIME && !HAVE_UTIME_NULL */
+
+ return(utime(file, UTP));
+}
+#undef UTP
+
+
+
+/********************************************************************
+ *
+ * update_timestamp()
+ *
+ * This function changes the timestamp to "now"
+ */
+
+static void update_timestamp()
+{
+ if (timedir_is_good) {
+ /* become root */
+ set_perms(PERM_ROOT, 0);
+
+ if (touch(timestampfile) < 0) {
+ int fd = open(timestampfile, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+
+ if (fd < 0)
+ perror("update_timestamp: open");
+ else
+ close(fd);
+ }
+
+ /* relinquish root */
+ set_perms(PERM_USER, 0);
+ }
+}
+
+
+
+/********************************************************************
+ *
+ * remove_timestamp()
+ *
+ * This function removes the timestamp ticket file
+ */
+
+void remove_timestamp()
+{
+#ifdef USE_TTY_TICKETS
+ char *p;
+
+ if (p = strrchr(tty, '/'))
+ p++;
+ else
+ p = tty;
+
+ (void) sprintf(timestampfile, "%s/%s.%s", _PATH_SUDO_TIMEDIR, user_name, p);
+#else
+ (void) sprintf(timestampfile, "%s/%s", _PATH_SUDO_TIMEDIR, user_name);
+#endif /* USE_TTY_TICKETS */
+
+ /* become root */
+ set_perms(PERM_ROOT, 0);
+
+ /* remove the ticket file */
+ (void) unlink(timestampfile);
+
+ /* relinquish root */
+ set_perms(PERM_USER, 0);
+}
+
+
+
+/********************************************************************
+ *
+ * check_passwd()
+ *
+ * This function grabs the user's password and checks with the password
+ * in /etc/passwd (or uses other specified authentication method).
+ */
+
+#ifdef HAVE_SECURID
+static void check_passwd()
+{
+ struct SD_CLIENT sd_dat, *sd; /* SecurID data block */
+ register int counter = TRIES_FOR_PASSWORD;
+
+ (void) memset ((VOID *)&sd_dat, 0, sizeof(sd_dat));
+ sd = &sd_dat;
+
+ /* Initialize SecurID. */
+ set_perms(PERM_ROOT, 0);
+ creadcfg();
+ if (sd_init(sd) != 0) {
+ (void) fprintf(stderr, "%s: Cannot contact SecurID server\n", Argv[0]);
+ exit(1);
+ }
+
+ /*
+ * you get TRIES_FOR_PASSWORD times to guess your password
+ */
+ while (counter > 0) {
+ if (sd_auth(sd) == ACM_OK) {
+ set_perms(PERM_USER, 0);
+ return;
+ }
+
+ --counter; /* otherwise, try again */
+#ifdef USE_INSULTS
+ (void) fprintf(stderr, "%s\n", INSULT);
+#else
+ (void) fprintf(stderr, "%s\n", INCORRECT_PASSWORD);
+#endif /* USE_INSULTS */
+ }
+ set_perms(PERM_USER, 0);
+
+ if (counter > 0) {
+ log_error(PASSWORD_NOT_CORRECT);
+ inform_user(PASSWORD_NOT_CORRECT);
+ } else {
+ log_error(PASSWORDS_NOT_CORRECT);
+ inform_user(PASSWORDS_NOT_CORRECT);
+ }
+
+ exit(1);
+}
+#else /* !HAVE_SECURID */
+static void check_passwd()
+{
+ char *pass; /* this is what gets entered */
+ register int counter = TRIES_FOR_PASSWORD;
+#if defined(HAVE_KERB4) && defined(USE_GETPASS)
+ char kpass[_PASSWD_LEN + 1];
+#endif /* HAVE_KERB4 && USE_GETPASS */
+
+#ifdef HAVE_SKEY
+ (void) memset((VOID *)&skey, 0, sizeof(skey));
+#endif /* HAVE_SKEY */
+#ifdef HAVE_OPIE
+ (void) memset((VOID *)&opie, 0, sizeof(opie));
+#endif /* HAVE_OPIE */
+
+ /*
+ * you get TRIES_FOR_PASSWORD times to guess your password
+ */
+ while (counter > 0) {
+
+#ifdef HAVE_SKEY
+ /* rewrite the prompt if using s/key since the challenge can change */
+ set_perms(PERM_ROOT, 0);
+ prompt = sudo_skeyprompt(&skey, prompt);
+ set_perms(PERM_USER, 0);
+#endif /* HAVE_SKEY */
+#ifdef HAVE_OPIE
+ /* rewrite the prompt if using OPIE since the challenge can change */
+ set_perms(PERM_ROOT, 0);
+ prompt = sudo_opieprompt(&opie, prompt);
+ set_perms(PERM_USER, 0);
+#endif /* HAVE_OPIE */
+
+ /* get a password from the user */
+#ifdef USE_GETPASS
+# ifdef HAVE_KERB4
+ (void) des_read_pw_string(kpass, sizeof(kpass) - 1, prompt, 0);
+ pass = kpass;
+# else
+ pass = (char *) getpass(prompt);
+# endif /* HAVE_KERB4 */
+#else
+ pass = tgetpass(prompt, PASSWORD_TIMEOUT * 60, user_name, shost);
+#endif /* USE_GETPASS */
+
+ /* Exit loop on nil password */
+ if (!pass || *pass == '\0') {
+ if (counter == TRIES_FOR_PASSWORD)
+ exit(0);
+ else
+ break;
+ }
+
+#ifdef HAVE_SKEY
+ /* Only check s/key db if the user exists there */
+ if (skey.keyfile) {
+ set_perms(PERM_ROOT, 0);
+ if (skeyverify(&skey, pass) == 0) {
+ set_perms(PERM_USER, 0);
+ return; /* if the key is correct return() */
+ }
+ set_perms(PERM_USER, 0);
+ }
+#endif /* HAVE_SKEY */
+#ifdef HAVE_OPIE
+ /* Only check OPIE db if the user exists there */
+ if (opie.opie_flags) {
+ set_perms(PERM_ROOT, 0);
+ if (opieverify(&opie, pass) == 0) {
+ set_perms(PERM_USER, 0);
+ return; /* if the key is correct return() */
+ }
+ set_perms(PERM_USER, 0);
+ }
+#endif /* HAVE_OPIE */
+#if !defined(HAVE_SKEY) || !defined(SKEY_ONLY)
+ /*
+ * If we use shadow passwords with a different crypt(3)
+ * check that here, else use standard crypt(3).
+ */
+# if (SHADOW_TYPE != SPW_NONE) && (SHADOW_TYPE != SPW_BSD)
+# if (SHADOW_TYPE == SPW_ULTRIX4)
+ if (!strcmp(user_passwd, (char *) crypt16(pass, user_passwd)))
+ return; /* if the passwd is correct return() */
+# endif /* ULTRIX4 */
+# if (SHADOW_TYPE == SPW_SECUREWARE) && !defined(__alpha)
+# ifdef HAVE_BIGCRYPT
+ if (strcmp(user_passwd, (char *) bigcrypt(pass, user_passwd)) == 0)
+ return; /* if the passwd is correct return() */
+# else
+ if (strcmp(user_passwd, crypt(pass, user_passwd)) == 0)
+ return; /* if the passwd is correct return() */
+# endif /* HAVE_BIGCRYPT */
+# endif /* SECUREWARE && !__alpha */
+# if (SHADOW_TYPE == SPW_SECUREWARE) && defined(__alpha)
+ if (crypt_type == AUTH_CRYPT_BIGCRYPT) {
+ if (!strcmp(user_passwd, bigcrypt(pass, user_passwd)))
+ return; /* if the passwd is correct return() */
+ } else if (crypt_type == AUTH_CRYPT_CRYPT16) {
+ if (!strcmp(user_passwd, crypt16(pass, user_passwd)))
+ return; /* if the passwd is correct return() */
+#ifdef AUTH_CRYPT_OLDCRYPT
+ } else if (crypt_type == AUTH_CRYPT_OLDCRYPT ||
+ crypt_type == AUTH_CRYPT_C1CRYPT) {
+ if (!strcmp(user_passwd, crypt(pass, user_passwd)))
+ return; /* if the passwd is correct return() */
+#endif
+ } else {
+ (void) fprintf(stderr,
+ "%s: Sorry, I don't know how to deal with crypt type %d.\n",
+ Argv[0], crypt_type);
+ exit(1);
+ }
+# endif /* SECUREWARE && __alpha */
+# endif /* SHADOW_TYPE != SPW_NONE && SHADOW_TYPE != SPW_BSD */
+
+ /* Normal UN*X password check */
+ if (!strcmp(user_passwd, (char *) crypt(pass, user_passwd)))
+ return; /* if the passwd is correct return() */
+
+# ifdef HAVE_KERB4
+ if (user_uid && sudo_krb_validate_user(user_pw_ent, pass) == 0)
+ return;
+# endif /* HAVE_KERB4 */
+
+# ifdef HAVE_AFS
+ if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION,
+ user_name, /* name */
+ NULL, /* instance */
+ NULL, /* realm */
+ pass, /* password */
+ 0, /* lifetime */
+ 0, 0, /* spare */
+ NULL) == 0) /* reason */
+ return;
+# endif /* HAVE_AFS */
+# ifdef HAVE_DCE
+ /*
+ * consult the DCE registry for password validation
+ * note that dce_pwent trashes pass upon return...
+ */
+ if (dce_pwent(user_name, pass))
+ return;
+# endif /* HAVE_DCE */
+#endif /* !HAVE_SKEY || !SKEY_ONLY */
+
+ --counter; /* otherwise, try again */
+#ifdef USE_INSULTS
+ (void) fprintf(stderr, "%s\n", INSULT);
+#else
+ (void) fprintf(stderr, "%s\n", INCORRECT_PASSWORD);
+#endif /* USE_INSULTS */
+ }
+
+ if (counter > 0) {
+ log_error(PASSWORD_NOT_CORRECT);
+ inform_user(PASSWORD_NOT_CORRECT);
+ } else {
+ log_error(PASSWORDS_NOT_CORRECT);
+ inform_user(PASSWORDS_NOT_CORRECT);
+ }
+
+ exit(1);
+}
+#endif /* HAVE_SECURID */
+
+
+#ifdef HAVE_KERB4
+/********************************************************************
+ *
+ * sudo_krb_validate_user()
+ *
+ * Validate a user via kerberos.
+ */
+static int sudo_krb_validate_user(pw_ent, pass)
+ struct passwd *pw_ent;
+ char *pass;
+{
+ char realm[REALM_SZ];
+ char tkfile[sizeof(_PATH_SUDO_TIMEDIR) + 4 + MAX_UID_T_LEN];
+ int k_errno;
+
+ /* Get the local realm */
+ if (krb_get_lrealm(realm, 1) != KSUCCESS)
+ (void) fprintf(stderr, "Warning: Unable to get local kerberos realm\n");
+
+ /*
+ * Set the ticket file to be in sudo sudo timedir so we don't
+ * wipe out other kerberos tickets.
+ */
+ (void) sprintf(tkfile, "%s/tkt%ld", _PATH_SUDO_TIMEDIR,
+ (long) pw_ent->pw_uid);
+ (void) krb_set_tkt_string(tkfile);
+
+ /*
+ * Update the ticket if password is ok. Kerb4 expects
+ * the ruid and euid to be the same here so we setuid to root.
+ */
+ set_perms(PERM_ROOT, 0);
+ k_errno = krb_get_pw_in_tkt(pw_ent->pw_name, "", realm, "krbtgt", realm,
+ DEFAULT_TKT_LIFE, pass);
+
+ /*
+ * If we authenticated, destroy the ticket now that we are done with it.
+ * If not, warn on a "real" error.
+ */
+ if (k_errno == INTK_OK)
+ dest_tkt();
+ else if (k_errno != INTK_BADPW && k_errno != KDC_PR_UNKNOWN)
+ (void) fprintf(stderr, "Warning: Kerberos error: %s\n",
+ krb_err_txt[k_errno]);
+
+ /* done with rootly stuff */
+ set_perms(PERM_USER, 0);
+
+ return(!(k_errno == INTK_OK));
+}
+#endif /* HAVE_KERB4 */
+
+
+#ifdef HAVE_SKEY
+/********************************************************************
+ *
+ * sudo_skeyprompt()
+ *
+ * This function rewrites and return the prompt based the
+ * s/key challenge * and fills in the user's skey structure.
+ */
+
+static char *sudo_skeyprompt(user_skey, p)
+ struct skey *user_skey;
+ char *p;
+{
+ char challenge[256];
+ int rval;
+ static char *orig_prompt = NULL, *new_prompt = NULL;
+ static int op_len, np_size;
+
+ /* save the original prompt */
+ if (orig_prompt == NULL) {
+ orig_prompt = p;
+ op_len = strlen(p);
+
+ /* ignore trailing colon */
+ if (p[op_len - 1] == ':')
+ op_len--;
+ }
+
+ /* close old stream */
+ if (user_skey->keyfile)
+ (void) fclose(user_skey->keyfile);
+
+ /* get the skey part of the prompt */
+ if ((rval = skeychallenge(user_skey, user_name, challenge)) != 0) {
+#ifdef OTP_ONLY
+ (void) fprintf(stderr,
+ "%s: You do not exist in the s/key database.\n",
+ Argv[0]);
+ exit(1);
+#else
+ /* return the original prompt if we cannot get s/key info */
+ return(orig_prompt);
+#endif /* OTP_ONLY */
+ }
+
+ /* get space for new prompt with embedded s/key challenge */
+ if (new_prompt == NULL) {
+ /* allocate space for new prompt */
+ np_size = op_len + strlen(challenge) + 7;
+ if (!(new_prompt = (char *) malloc(np_size))) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ } else {
+ /* already have space allocated, is it enough? */
+ if (np_size < op_len + strlen(challenge) + 7) {
+ np_size = op_len + strlen(challenge) + 7;
+ if (!(new_prompt = (char *) realloc(new_prompt, np_size))) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n",
+ Argv[0]);
+ exit(1);
+ }
+ }
+ }
+
+ /* embed the s/key challenge into the new password prompt */
+#ifdef LONG_OTP_PROMPT
+ (void) sprintf(new_prompt, "%s\n%s", challenge, orig_prompt);
+#else
+ (void) sprintf(new_prompt, "%.*s [ %s ]:", op_len, orig_prompt, challenge);
+#endif /* LONG_OTP_PROMPT */
+
+ return(new_prompt);
+}
+#endif /* HAVE_SKEY */
+
+
+#ifdef HAVE_OPIE
+/********************************************************************
+ *
+ * sudo_opieprompt()
+ *
+ * This function rewrites and return the prompt based the
+ * OPIE challenge * and fills in the user's opie structure.
+ */
+
+static char *sudo_opieprompt(user_opie, p)
+ struct opie *user_opie;
+ char *p;
+{
+ char challenge[OPIE_CHALLENGE_MAX];
+ int rval;
+ static char *orig_prompt = NULL, *new_prompt = NULL;
+ static int op_len, np_size;
+
+ /* save the original prompt */
+ if (orig_prompt == NULL) {
+ orig_prompt = p;
+ op_len = strlen(p);
+
+ /* ignore trailing colon */
+ if (p[op_len - 1] == ':')
+ op_len--;
+ }
+
+ /* get the opie part of the prompt */
+ if ((rval = opiechallenge(user_opie, user_name, challenge)) != 0) {
+#ifdef OTP_ONLY
+ (void) fprintf(stderr,
+ "%s: You do not exist in the s/key database.\n",
+ Argv[0]);
+ exit(1);
+#else
+ /* return the original prompt if we cannot get s/key info */
+ return(orig_prompt);
+#endif /* OTP_ONLY */
+ }
+
+ /* get space for new prompt with embedded s/key challenge */
+ if (new_prompt == NULL) {
+ /* allocate space for new prompt */
+ np_size = op_len + strlen(challenge) + 7;
+ if (!(new_prompt = (char *) malloc(np_size))) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ } else {
+ /* already have space allocated, is it enough? */
+ if (np_size < op_len + strlen(challenge) + 7) {
+ np_size = op_len + strlen(challenge) + 7;
+ if (!(new_prompt = (char *) realloc(new_prompt, np_size))) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n",
+ Argv[0]);
+ exit(1);
+ }
+ }
+ }
+
+ /* embed the s/key challenge into the new password prompt */
+#ifdef LONG_OTP_PROMPT
+ (void) sprintf(new_prompt, "%s\n%s", challenge, orig_prompt);
+#else
+ (void) sprintf(new_prompt, "%.*s [ %s ]:", op_len, orig_prompt, challenge);
+#endif /* LONG_OTP_PROMPT */
+
+ return(new_prompt);
+}
+#endif /* HAVE_OPIE */
+
+
+#ifndef NO_MESSAGE
+/********************************************************************
+ *
+ * reminder()
+ *
+ * this function just prints the the reminder message
+ */
+
+static void reminder()
+{
+#ifdef SHORT_MESSAGE
+ (void) fprintf(stderr, "\n%s\n%s\n\n%s\n%s\n\n",
+#else
+ (void) fprintf(stderr, "\n%s\n%s\n%s\n%s\n\n%s\n%s\n\n%s\n%s\n\n",
+ " CU sudo version 1.5.2, based on Root Group sudo version 1.1",
+ " sudo version 1.1, Copyright (C) 1991 The Root Group, Inc.",
+ " sudo comes with ABSOLUTELY NO WARRANTY. This is free software,",
+ " and you are welcome to redistribute it under certain conditions.",
+#endif
+ "We trust you have received the usual lecture from the local System",
+ "Administrator. It usually boils down to these two things:",
+ " #1) Respect the privacy of others.",
+ " #2) Think before you type."
+ );
+
+ (void) fflush(stderr);
+}
+#endif /* NO_MESSAGE */
diff --git a/gnu/usr.bin/sudo/sudo/compat.h b/gnu/usr.bin/sudo/sudo/compat.h
new file mode 100644
index 00000000000..d2ae270ab64
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/compat.h
@@ -0,0 +1,145 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ * $Id: compat.h,v 1.1 1996/10/14 05:14:44 millert Exp $
+ */
+
+#ifndef _SUDO_COMPAT_H
+#define _SUDO_COMPAT_H
+
+/*
+ * Macros that may be missing on some Operating Systems
+ */
+
+/* Deal with ansi stuff reasonably. */
+#ifndef __P
+# if defined (__cplusplus) || defined (__STDC__)
+# define __P(args) args
+# else
+# define __P(args) ()
+# endif
+#endif /* __P */
+
+/*
+ * Some systems (ie ISC V/386) do not define MAXPATHLEN even in param.h
+ */
+#ifndef MAXPATHLEN
+# define MAXPATHLEN 1024
+#endif
+
+/*
+ * Some systems do not define MAXHOSTNAMELEN.
+ */
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 64
+#endif
+
+/*
+ * 4.2BSD lacks FD_* macros (we only use FD_SET and FD_ZERO)
+ */
+#ifndef FD_SETSIZE
+#define FD_SET(fd, fds) ((fds) -> fds_bits[0] |= (1 << (fd)))
+#define FD_ZERO(fds) ((fds) -> fds_bits[0] = 0)
+#endif /* !FD_SETSIZE */
+
+/*
+ * Posix versions for those without...
+ */
+#ifndef _S_IFMT
+# define _S_IFMT S_IFMT
+#endif /* _S_IFMT */
+#ifndef _S_IFREG
+# define _S_IFREG S_IFREG
+#endif /* _S_IFREG */
+#ifndef _S_IFDIR
+# define _S_IFDIR S_IFDIR
+#endif /* _S_IFDIR */
+#ifndef S_ISREG
+# define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
+#endif /* S_ISREG */
+#ifndef S_ISDIR
+# define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
+#endif /* S_ISDIR */
+
+/*
+ * Some OS's may not have this.
+ */
+#ifndef S_IRWXU
+# define S_IRWXU 0000700 /* rwx for owner */
+#endif /* S_IRWXU */
+
+/*
+ * We need to know how long the longest password may be.
+ * For alternate password schemes we need longer passwords.
+ * This is a bit, ummm, gross but necesary.
+ */
+#if defined(HAVE_KERB4) || defined(HAVE_AFS) || defined(HAVE_DCE) || defined(HAVE_SKEY) || defined(HAVE_OPIE)
+# undef _PASSWD_LEN
+# define _PASSWD_LEN 256
+#else
+# if (SHADOW_TYPE == SPW_SECUREWARE)
+# undef _PASSWD_LEN
+# define _PASSWD_LEN AUTH_MAX_PASSWD_LENGTH
+# else
+# ifndef _PASSWD_LEN
+# ifdef PASS_MAX
+# define _PASSWD_LEN PASS_MAX
+# else
+# if (SHADOW_TYPE != SPW_NONE)
+# define _PASSWD_LEN 24
+# else
+# define _PASSWD_LEN 8
+# endif /* SHADOW_TYPE != SPW_NONE */
+# endif /* PASS_MAX */
+# endif /* !_PASSWD_LEN */
+# endif /* HAVE_KERB4 || HAVE_AFS || HAVE_DCE || HAVE_SKEY || HAVE_OPIE */
+#endif /* SPW_SECUREWARE */
+
+/*
+ * Some OS's lack these
+ */
+#ifndef UID_NO_CHANGE
+# define UID_NO_CHANGE ((uid_t) -1)
+#endif /* UID_NO_CHANGE */
+#ifndef GID_NO_CHANGE
+# define GID_NO_CHANGE ((gid_t) -1)
+#endif /* GID_NO_CHANGE */
+
+/*
+ * Emulate seteuid() for AIX via setuidx() -- needed for some versions of AIX
+ */
+#ifdef _AIX
+# include <sys/id.h>
+# define seteuid(_EUID) (setuidx(ID_EFFECTIVE|ID_REAL, _EUID))
+# undef HAVE_SETEUID
+# define HAVE_SETEUID 1
+#endif /* _AIX */
+
+/*
+ * Emulate seteuid() for HP-UX via setresuid(2) and seteuid(2) for others.
+ */
+#ifndef HAVE_SETEUID
+# ifdef __hpux
+# define seteuid(_EUID) (setresuid(UID_NO_CHANGE, _EUID, UID_NO_CHANGE))
+# else
+# define seteuid(_EUID) (setresuid(UID_NO_CHANGE, _EUID))
+# endif /* __hpux */
+#endif /* HAVE_SETEUID */
+
+#endif /* _SUDO_COMPAT_H */
diff --git a/gnu/usr.bin/sudo/sudo/config.h b/gnu/usr.bin/sudo/sudo/config.h
new file mode 100644
index 00000000000..a9dc67a9ce3
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/config.h
@@ -0,0 +1,304 @@
+/* config.h. Generated automatically by configure. */
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ * $Id: config.h,v 1.1 1996/10/14 05:14:44 millert Exp $
+ */
+
+/*
+ * config.h -- You shouldn't edit this by hand unless you are
+ * NOT using configure.
+ */
+
+/* New ANSI-style OS defs. */
+#if defined(hpux) && !defined(__hpux)
+# define __hpux 1
+#endif /* hpux */
+
+#if defined(convex) && !defined(__convex__)
+# define __convex__ 1
+#endif /* convex */
+
+/* Define if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
+#endif
+
+/* Define if on ConvexOs.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _CONVEX_SOURCE
+/* #undef _CONVEX_SOURCE */
+#endif
+
+/* Define if needed to get POSIX functionality.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _POSIX_SOURCE
+/* #undef _POSIX_SOURCE */
+#endif
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef ssize_t */
+
+/* Define to be nil if C compiler doesn't support "const." */
+/* #undef const */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you want to use the system getpass(). */
+/* #undef USE_GETPASS */
+
+/* Define if you use S/Key. */
+/* #undef HAVE_SKEY */
+
+/* Define if you use NRL OPIE. */
+/* #undef HAVE_OPIE */
+
+/* Define if you use SecurID. */
+/* #undef HAVE_SECURID */
+
+/* Define if you use Kerberos. */
+/* #undef HAVE_KERB4 */
+
+/* Define if you use Kerberos. */
+/* #undef HAVE_KERB5 */
+
+/* Keberos v5 has v4 compatibility */
+#ifdef HAVE_KERB5
+# define HAVE_KERB4
+#endif /* HAVE_KERB5 */
+
+/* Define if you use AFS. */
+/* #undef HAVE_AFS */
+
+/* Define if you use OSF DCE. */
+/* #undef HAVE_DCE */
+
+/* Define if you have POSIX signals. */
+#define HAVE_SIGACTION 1
+#ifdef HAVE_SIGACTION
+# define POSIX_SIGNALS
+#endif /* HAVE_SIGACTION */
+
+/* Define if you have tzset(3). */
+#define HAVE_TZSET 1
+
+/* Define if you have getcwd(3). */
+/* #undef HAVE_GETCWD */
+
+/* Define if you have getwd(3). */
+#define HAVE_GETWD 1
+
+/* Define if you have strdup(3). */
+#define HAVE_STRDUP 1
+
+/* Define if you have fnmatch(3). */
+#define HAVE_FNMATCH 1
+
+/* Define if you have lsearch(3). */
+#define HAVE_LSEARCH 1
+
+/* Define if you have strchr(3). */
+#define HAVE_STRCHR 1
+#if !defined(HAVE_STRCHR) && !defined(strchr)
+# define strchr index
+#endif
+
+/* Define if you have strrchr(3). */
+#define HAVE_STRRCHR 1
+#if !defined(HAVE_STRRCHR) && !defined(strrchr)
+# define strrchr rindex
+#endif
+
+/* Define if you have memcpy(3). */
+#define HAVE_MEMCPY 1
+#if !defined(HAVE_MEMCPY) && !defined(memcpy)
+# define memcpy(D, S, L) (bcopy(S, D, L))
+#endif
+
+/* Define if you have memset(3). */
+#define HAVE_MEMSET 1
+#if !defined(HAVE_MEMSET) && !defined(memset)
+# define memset(S, X, N) (bzero(S, N))
+#endif
+
+/* Define if you have sysconf(3c). */
+#define HAVE_SYSCONF 1
+
+/* Define if you have putenv(3). */
+/* #undef HAVE_PUTENV */
+
+/* Define if you have setenv(3). */
+#define HAVE_SETENV 1
+
+/* Define if you have strcasecmp(3). */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have tcgetattr(3). */
+#define HAVE_TCGETATTR 1
+
+/* Define if you have innetgr(3). */
+#define HAVE_INNETGR 1
+
+/* Define if you have getdomainname(2). */
+#define HAVE_GETDOMAINNAME 1
+
+/* Define if you have utime(2). */
+#define HAVE_UTIME 1
+
+/* Define if you have a POSIX utime() (uses struct utimbuf) */
+#define HAVE_UTIME_POSIX 1
+
+/* Define if utime(file, NULL) sets timestamp to current */
+#define HAVE_UTIME_NULL 1
+
+/* Define if you have bigcrypt(3). */
+/* #undef HAVE_BIGCRYPT */
+
+/* Define if you have seteuid(3). */
+#define HAVE_SETEUID 1
+
+/* Define if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define if you have the <alloca.h> header file. */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#if !defined(__convex__) && !defined(convex)
+#define HAVE_STRINGS_H 1
+#endif /* convex */
+
+/* Define your flavor of dir entry header file. */
+#define HAVE_DIRENT_H 1
+/* #undef HAVE_SYS_NDIR_H */
+/* #undef HAVE_SYS_DIR_H */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <fnmatch.h> header file. */
+#define HAVE_FNMATCH_H 1
+
+/* Define if you have the <netgroup.h> header file. */
+#define HAVE_NETGROUP_H 1
+
+/* Define if you have the <termio.h> header file. */
+/* #undef HAVE_TERMIO_H */
+
+/* Define if you have the <termios.h> header file and tcgetattr(3). */
+#ifdef HAVE_TCGETATTR
+#define HAVE_TERMIOS_H 1
+#endif /* HAVE_TCGETATTR */
+
+/* Define if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define if you have the <sys/bsdtypes.h> header file. */
+/* #undef HAVE_SYS_BSDTYPES_H */
+
+/* Define if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if your struct sockadr has an sa_len field. */
+#define HAVE_SA_LEN 1
+
+/* Supported shadow password types */
+#define SPW_NONE 0x00
+#define SPW_SECUREWARE 0x01
+#define SPW_HPUX9 0x02
+#define SPW_SUNOS4 0x03
+#define SPW_SVR4 0x04
+#define SPW_ULTRIX4 0x05
+#define SPW_BSD 0x06
+
+/* Define to the variety of shadow passwords supported on your OS */
+#define SHADOW_TYPE SPW_BSD
+
+/* Define to void if your C compiler fully groks void, else char */
+#define VOID void
+
+/* Define to the max length of a uid_t in string context (excluding the NULL */
+#define MAX_UID_T_LEN 10
+
+/* Define if your syslog(3) does not guarantee the message will be logged */
+/* and syslog(3) returns non-zero to denote failure */
+/* #undef BROKEN_SYSLOG */
+
+/*
+ * Paths to commands used by sudo. There are used by pathnames.h.
+ * If you want to override these values, do so in pathnames.h, not here!
+ */
+
+#ifndef _CONFIG_PATH_SENDMAIL
+#define _CONFIG_PATH_SENDMAIL "/usr/sbin/sendmail"
+#endif /* _CONFIG_PATH_SENDMAIL */
+
+#ifndef _CONFIG_PATH_VI
+#define _CONFIG_PATH_VI "/usr/bin/vi"
+#endif /* _CONFIG_PATH_VI */
+
+#ifndef _CONFIG_PATH_PWD
+#define _CONFIG_PATH_PWD "/bin/pwd"
+#endif /* _CONFIG_PATH_PWD */
+
+#ifndef _CONFIG_PATH_MV
+#define _CONFIG_PATH_MV "/bin/mv"
+#endif /* _CONFIG_PATH_MV */
+
+#ifndef _CONFIG_PATH_BSHELL
+#define _CONFIG_PATH_BSHELL "/bin/sh"
+#endif /* _CONFIG_PATH_BSHELL */
+
+#ifndef _CONFIG_PATH_LOGFILE
+#define _CONFIG_PATH_LOGFILE "/var/log/sudo.log"
+#endif /* _CONFIG_PATH_LOGFILE */
+
+#ifndef _CONFIG_PATH_TIMEDIR
+#define _CONFIG_PATH_TIMEDIR "/var/run/sudo"
+#endif /* _CONFIG_PATH_TIMEDIR */
diff --git a/gnu/usr.bin/sudo/sudo/find_path.c b/gnu/usr.bin/sudo/sudo/find_path.c
new file mode 100644
index 00000000000..e0b0b6aa512
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/find_path.c
@@ -0,0 +1,187 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ *******************************************************************
+ *
+ * This module contains the find_path() function that returns
+ * TRUE if the command was found and FALSE if not.
+ * If find_path() returns TRUE, the copyin paramters command and
+ * ocommand contain the resolved and unresolved pathnames respectively.
+ * NOTE: if "." or "" exists in PATH it will be searched last.
+ *
+ * Todd C. Miller (millert@colorado.edu) Sat Mar 25 21:50:36 MST 1995
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: find_path.c,v 1.1 1996/10/14 05:14:45 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+#include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include "sudo.h"
+#include <options.h>
+
+#ifndef STDC_HEADERS
+#ifndef __GNUC__ /* gcc has its own malloc */
+extern char *malloc __P((size_t));
+#endif /* __GNUC__ */
+extern char *getenv __P((const char *));
+extern char *strcpy __P((char *, const char *));
+extern int fprintf __P((FILE *, const char *, ...));
+extern ssize_t readlink __P((const char *, VOID *, size_t));
+extern int stat __P((const char *, struct stat *));
+extern int lstat __P((const char *, struct stat *));
+#ifdef HAVE_STRDUP
+extern char *strdup __P((const char *));
+#endif /* HAVE_STRDUP */
+#endif /* !STDC_HEADERS */
+
+
+#ifndef _S_IFMT
+#define _S_IFMT S_IFMT
+#endif /* _S_IFMT */
+#ifndef _S_IFLNK
+#define _S_IFLNK S_IFLNK
+#endif /* _S_IFLNK */
+
+
+/*******************************************************************
+ *
+ * find_path()
+ *
+ * this function finds the full pathname for a command and
+ * stores it in a statically allocated array, returning a pointer
+ * to the array.
+ */
+
+char * find_path(file)
+ char *file; /* file to find */
+{
+ static char command[MAXPATHLEN + 1]; /* qualified filename */
+ register char *n; /* for traversing path */
+ char *path = NULL; /* contents of PATH env var */
+ char *origpath; /* so we can free path later */
+ char *result = NULL; /* result of path/file lookup */
+#ifndef IGNORE_DOT_PATH
+ int checkdot = 0; /* check current dir? */
+#endif /* IGNORE_DOT_PATH */
+
+ command[0] = '\0';
+
+ if (strlen(file) > MAXPATHLEN) {
+ errno = ENAMETOOLONG;
+ (void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], file);
+ exit(1);
+ }
+
+ /*
+ * If we were given a fully qualified or relative path
+ * there is no need to look at PATH.
+ * We really want to fall back if !sudo_goodpath() but then
+ * the error is "not found" -- this way we get the correct error.
+ */
+ if (strchr(file, '/')) {
+ (void) strcpy(command, file);
+ if (sudo_goodpath(command)) {
+ return(command);
+ } else {
+ (void) fprintf(stderr, "%s: %s: ", Argv[0], command);
+ perror("");
+ exit(1);
+ }
+ }
+
+ /*
+ * grab PATH out of environment and make a local copy
+ */
+ if ((path = getenv("PATH")) == NULL)
+ return(NULL);
+
+ if ((path = (char *) strdup(path)) == NULL) {
+ (void) fprintf(stderr, "%s: out of memory!\n", Argv[0]);
+ exit(1);
+ }
+ origpath=path;
+
+ /* XXX use strtok() */
+ do {
+ if ((n = strchr(path, ':')))
+ *n = '\0';
+
+ /*
+ * search current dir last if it is in PATH This will miss sneaky
+ * things like using './' or './/'
+ */
+ if (*path == '\0' || (*path == '.' && *(path + 1) == '\0')) {
+#ifndef IGNORE_DOT_PATH
+ checkdot = 1;
+#endif /* IGNORE_DOT_PATH */
+ path = n + 1;
+ continue;
+ }
+
+ /*
+ * resolve the path and exit the loop if found
+ */
+ if (strlen(path) + strlen(file) >= MAXPATHLEN) {
+ errno = ENAMETOOLONG;
+ (void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], file);
+ exit(1);
+ }
+ (void) sprintf(command, "%s/%s", path, file);
+ if ((result = sudo_goodpath(command)))
+ break;
+
+ path = n + 1;
+
+ } while (n);
+
+#ifndef IGNORE_DOT_PATH
+ /*
+ * check current dir if dot was in the PATH
+ */
+ if (!result && checkdot)
+ result = sudo_goodpath(file);
+#endif /* IGNORE_DOT_PATH */
+
+ (void) free(origpath);
+
+ return(result);
+}
diff --git a/gnu/usr.bin/sudo/sudo/getspwuid.c b/gnu/usr.bin/sudo/sudo/getspwuid.c
new file mode 100644
index 00000000000..7ff4a16185c
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/getspwuid.c
@@ -0,0 +1,266 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ *******************************************************************
+ *
+ * This module contains sudo_getpwuid(), a function that
+ * Makes a dynamic copy of the struct passwd returned by
+ * getpwuid() and substitutes the shadow password if
+ * necesary.
+ *
+ * Todd C. Miller Mon Nov 20 13:53:06 MST 1995
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: getspwuid.c,v 1.1 1996/10/14 05:14:46 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+#include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <pwd.h>
+#include "sudo.h"
+#include <options.h>
+#if (SHADOW_TYPE != SPW_NONE) && (SHADOW_TYPE != SPW_BSD)
+# if (SHADOW_TYPE == SPW_SVR4)
+# include <shadow.h>
+# endif /* SVR4 */
+# if (SHADOW_TYPE == SPW_SECUREWARE)
+# ifdef __hpux
+# include <hpsecurity.h>
+# else
+# include <sys/security.h>
+# endif /* __hpux */
+# include <prot.h>
+# endif /* SECUREWARE */
+# if (SHADOW_TYPE == SPW_ULTRIX4)
+# include <auth.h>
+# endif /* ULTRIX4 */
+# if (SHADOW_TYPE == SPW_SUNOS4)
+# include <sys/label.h>
+# include <sys/audit.h>
+# include <pwdadj.h>
+# endif /* SUNOS4 */
+#endif /* SHADOW_TYPE != SPW_NONE && SHADOW_TYPE != SPW_BSD */
+
+#ifndef STDC_HEADERS
+#ifndef __GNUC__ /* gcc has its own malloc */
+extern char *malloc __P((size_t));
+#endif /* __GNUC__ */
+extern char *getenv __P((const char *));
+#ifdef HAVE_STRDUP
+extern char *strdup __P((const char *));
+#endif /* HAVE_STRDUP */
+#endif /* !STDC_HEADERS */
+
+/*
+ * Global variables (yuck)
+ */
+#if (SHADOW_TYPE == SPW_SECUREWARE) && defined(__alpha)
+uchar_t crypt_type;
+#endif /* SPW_SECUREWARE && __alpha */
+
+
+/*
+ * Local functions not visible outside getspwuid.c
+ */
+static char *sudo_getshell __P((struct passwd *));
+static char *sudo_getspwd __P((struct passwd *));
+
+
+
+/**********************************************************************
+ *
+ * sudo_getshell()
+ *
+ * This function returns the user's shell based on either the
+ * SHELL evariable or the passwd(5) entry (in that order).
+ */
+
+static char *sudo_getshell(pw_ent)
+ struct passwd *pw_ent;
+{
+ char *pw_shell;
+
+ if ((pw_shell = getenv("SHELL")) == NULL)
+ pw_shell = pw_ent -> pw_shell;
+
+#ifdef _PATH_BSHELL
+ /* empty string "" means bourne shell */
+ if (*pw_shell == '\0')
+ pw_shell = _PATH_BSHELL;
+#endif /* _PATH_BSHELL */
+
+ return(pw_shell);
+}
+
+
+/**********************************************************************
+ *
+ * sudo_getspwd()
+ *
+ * This function returns the shadow password for the user described
+ * by pw_ent. If there is no shadow password the normal UN*X password
+ * is returned instead.
+ */
+
+static char *sudo_getspwd(pw_ent)
+ struct passwd *pw_ent;
+#if (SHADOW_TYPE != SPW_NONE) && (SHADOW_TYPE != SPW_BSD)
+# if (SHADOW_TYPE == SPW_SVR4)
+{
+ struct spwd *spw_ent;
+
+ if ((spw_ent = getspnam(pw_ent -> pw_name)) && spw_ent -> sp_pwdp)
+ return(spw_ent -> sp_pwdp);
+ else
+ return(pw_ent -> pw_passwd);
+}
+# endif /* SVR4 */
+# if (SHADOW_TYPE == SPW_HPUX9)
+{
+ struct s_passwd *spw_ent;
+
+ if ((spw_ent = getspwuid(pw_ent -> pw_uid)) && spw_ent -> pw_passwd)
+ return(spw_ent -> pw_passwd);
+ else
+ return(pw_ent -> pw_passwd);
+}
+# endif /* HPUX9 */
+# if (SHADOW_TYPE == SPW_SUNOS4)
+{
+ struct passwd_adjunct *spw_ent;
+
+ if ((spw_ent = getpwanam(pw_ent -> pw_name)) && spw_ent -> pwa_passwd)
+ return(spw_ent -> pwa_passwd);
+ else
+ return(pw_ent -> pw_passwd);
+}
+# endif /* SUNOS4 */
+# if (SHADOW_TYPE == SPW_ULTRIX4)
+{
+ AUTHORIZATION *spw_ent;
+
+ if ((spw_ent = getauthuid(pw_ent -> pw_uid)) && spw_ent -> a_password)
+ return(spw_ent -> a_password);
+ else
+ return(pw_ent -> pw_passwd);
+}
+# endif /* ULTRIX4 */
+# if (SHADOW_TYPE == SPW_SECUREWARE)
+{
+ struct pr_passwd *spw_ent;
+
+ if ((spw_ent = getprpwuid(pw_ent->pw_uid)) && spw_ent->ufld.fd_encrypt) {
+# ifdef __alpha
+ crypt_type = spw_ent -> ufld.fd_oldcrypt;
+# ifdef AUTH_CRYPT_C1CRYPT
+ if (crypt_type == AUTH_CRYPT_C1CRYPT)
+ return(pw_ent -> pw_passwd);
+# endif /* AUTH_CRYPT_C1CRYPT */
+# endif /* __alpha */
+ return(spw_ent -> ufld.fd_encrypt);
+ } else
+ return(pw_ent -> pw_passwd);
+}
+# endif /* SECUREWARE */
+#else
+{
+ return(pw_ent->pw_passwd);
+}
+#endif /* SHADOW_TYPE != SPW_NONE && SHADOW_TYPE != SPW_BSD */
+
+
+/**********************************************************************
+ *
+ * sudo_getpwuid()
+ *
+ * This function dynamically allocates space for a struct password
+ * and the constituent parts that we care about. If shadow passwords
+ * are in use, it substitutes the shadow password for pw_passwd.
+ */
+
+struct passwd *sudo_getpwuid(uid)
+ uid_t uid;
+{
+ struct passwd *pw_ent, *local_pw_ent;
+
+ if ((pw_ent = getpwuid(uid)) == NULL)
+ return(NULL);
+
+ /* allocate space for a local copy of pw_ent */
+ local_pw_ent = (struct passwd *) malloc(sizeof(struct passwd));
+ if (local_pw_ent == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ /*
+ * Copy the struct passwd and the interesting strings...
+ */
+ (void) memcpy(local_pw_ent, pw_ent, sizeof(struct passwd));
+
+ local_pw_ent->pw_name = (char *) strdup(pw_ent->pw_name);
+ if (local_pw_ent->pw_name == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ local_pw_ent->pw_dir = (char *) strdup(pw_ent->pw_dir);
+ if (local_pw_ent->pw_dir == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ /* pw_shell is a special case since we overide with $SHELL */
+ local_pw_ent->pw_shell = (char *) strdup(sudo_getshell(pw_ent));
+ if (local_pw_ent->pw_shell == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ /* pw_passwd gets a shadow password if applicable */
+ local_pw_ent->pw_passwd = (char *) strdup(sudo_getspwd(pw_ent));
+ if (local_pw_ent->pw_passwd == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ return(local_pw_ent);
+}
diff --git a/gnu/usr.bin/sudo/sudo/goodpath.c b/gnu/usr.bin/sudo/sudo/goodpath.c
new file mode 100644
index 00000000000..61a19ac84d9
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/goodpath.c
@@ -0,0 +1,99 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ *******************************************************************
+ *
+ * This module contains sudo_goodpath(3)
+ *
+ * sudo_goodpath(3) takes a path to check and returns its argument
+ * if the path is stat(2)'able, a regular file, and executable by
+ * root. The string's size should be <= MAXPATHLEN.
+ *
+ * Todd C. Miller (millert@colorado.edu) Sat Mar 25 21:58:17 MST 1995
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: goodpath.c,v 1.1 1996/10/14 05:14:46 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+
+#include "sudo.h"
+#include <options.h>
+
+#ifndef STDC_HEADERS
+extern int stat __P((const char *, struct stat *));
+#endif /* !STDC_HEADERS */
+
+
+/******************************************************************
+ *
+ * sudo_goodpath()
+ *
+ * this function takes a path and makes sure it describes a a file
+ * that is a normal file and executable by root.
+ */
+
+char * sudo_goodpath(path)
+ const char * path;
+{
+ struct stat statbuf; /* for stat(2) */
+ int err; /* if stat(2) got an error */
+
+ /* check for brain damage */
+ if (path == NULL || path[0] == '\0')
+ return(NULL);
+
+ /* we need to be root for the stat */
+ set_perms(PERM_ROOT, 0);
+
+ err = stat(path, &statbuf);
+
+ /* discard root perms */
+ set_perms(PERM_USER, 0);
+
+ /* stat(3) failed */
+ if (err)
+ return(NULL);
+
+ /* make sure path describes an executable regular file */
+ if (S_ISREG(statbuf.st_mode) && (statbuf.st_mode & 0000111)) {
+ return((char *)path);
+ } else {
+ /* file is not executable/regular */
+ errno = EACCES;
+ return(NULL);
+ }
+}
diff --git a/gnu/usr.bin/sudo/sudo/ins_2001.h b/gnu/usr.bin/sudo/sudo/ins_2001.h
new file mode 100644
index 00000000000..b062f17f795
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/ins_2001.h
@@ -0,0 +1,39 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ * $Id: ins_2001.h,v 1.1 1996/10/14 05:14:47 millert Exp $
+ */
+
+#ifndef _SUDO_INS_2001_H
+#define _SUDO_INS_2001_H
+
+ /*
+ * HAL insults (paraphrased) from 2001.
+ */
+
+ "Just what do you think you're doing Dave?",
+ "It can only be attributed to human error.",
+ "That's something I cannot allow to happen.",
+ "My mind is going. I can feel it.",
+ "Sorry about this, I know it's a bit silly.",
+ "Take a stress pill and think things over.",
+ "This mission is too important for me to allow you to jeopardize it.",
+ "I feel much better now.",
+
+#endif /* _SUDO_INS_2001_H */
diff --git a/gnu/usr.bin/sudo/sudo/ins_classic.h b/gnu/usr.bin/sudo/sudo/ins_classic.h
new file mode 100644
index 00000000000..2f395bd6c29
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/ins_classic.h
@@ -0,0 +1,39 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ * $Id: ins_classic.h,v 1.1 1996/10/14 05:14:47 millert Exp $
+ */
+
+#ifndef _SUDO_INS_CLASSIC_H
+#define _SUDO_INS_CLASSIC_H
+
+ /*
+ * Insults from the original sudo(8).
+ */
+
+ "Wrong! You cheating scum!",
+ "No soap, honkie-lips.",
+ "Where did you learn to type?",
+ "Are you on drugs?",
+ "My pet ferret can type better than you!",
+ "You type like i drive.",
+ "Do you think like you type?",
+ "Your mind just hasn't been the same since the electro-shock, has it?",
+
+#endif /* _SUDO_INS_CLASSIC_H */
diff --git a/gnu/usr.bin/sudo/sudo/ins_csops.h b/gnu/usr.bin/sudo/sudo/ins_csops.h
new file mode 100644
index 00000000000..b948e0bb447
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/ins_csops.h
@@ -0,0 +1,40 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ * $Id: ins_csops.h,v 1.1 1996/10/14 05:14:48 millert Exp $
+ */
+
+#ifndef _SUDO_INS_CSOPS_H
+#define _SUDO_INS_CSOPS_H
+
+ /*
+ * CSOps insults (may be site dependent).
+ */
+
+ "Maybe if you used more than just two fingers...",
+ "BOB says: You seem to have forgotten your passwd, enter another!",
+ "stty: unknown mode: doofus",
+ "I can't hear you -- I'm using the scrambler.",
+ "The more you drive -- the dumber you get.",
+ "Listen, burrito brains, I don't have time to listen to this trash.",
+ "I've seen penguins that can type better than that.",
+ "Have you considered trying to match wits with a rutabaga?",
+ "You speak an infinite deal of nothing",
+
+#endif /* _SUDO_INS_CSOPS_H */
diff --git a/gnu/usr.bin/sudo/sudo/ins_goons.h b/gnu/usr.bin/sudo/sudo/ins_goons.h
new file mode 100644
index 00000000000..3fade04a3d1
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/ins_goons.h
@@ -0,0 +1,54 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ * $Id: ins_goons.h,v 1.1 1996/10/14 05:14:48 millert Exp $
+ */
+
+#ifndef _SUDO_INS_GOONS_H
+#define _SUDO_INS_GOONS_H
+
+ /*
+ * Insults from the "Goon Show."
+ */
+
+ "You silly, twisted boy you.",
+ "He has fallen in the water!",
+ "We'll all be murdered in our beds!",
+ "You can't come in. Our tiger has got flu",
+ "I don't wish to know that.",
+ "What, what, what, what, what, what, what, what, what, what?",
+ "You can't get the wood, you know.",
+ "You'll starve!",
+ "... and it used to be so popular...",
+ "Pauses for audience applause, not a sausage",
+ "Hold it up to the light --- not a brain in sight!",
+ "Have a gorilla...",
+ "There must be cure for it!",
+ "There's a lot of it about, you know.",
+ "You do that again and see what happens...",
+ "Ying Tong Iddle I Po",
+ "Harm can come to a young lad like that!",
+ "And with that remarks folks, the case of the Crown vs yourself was proven.",
+ "Speak English you fool --- there are no subtitles in this scene.",
+ "You gotta go owwwww!",
+ "I have been called worse.",
+ "It's only your word against mine.",
+ "I think ... err ... I think ... I think I'll go home",
+
+#endif /* _SUDO_INS_GOONS_H */
diff --git a/gnu/usr.bin/sudo/sudo/insults.h b/gnu/usr.bin/sudo/sudo/insults.h
new file mode 100644
index 00000000000..013d05b50ba
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/insults.h
@@ -0,0 +1,71 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ * $Id: insults.h,v 1.1 1996/10/14 05:14:49 millert Exp $
+ */
+
+#ifndef _SUDO_INSULTS_H
+#define _SUDO_INSULTS_H
+
+#ifdef USE_INSULTS
+
+#if !defined(HAL_INSULTS) && !defined(GOONS_INSULTS) && !defined(CLASSIC_INSULTS)
+# define CLASSIC_INSULTS
+# define CSOPS_INSULTS
+#endif
+
+/*
+ * Use one or more set of insults as defined in options.h.
+ */
+
+char *insults[] = {
+
+# ifdef HAL_INSULTS
+# include "ins_2001.h"
+# endif
+
+# ifdef GOONS_INSULTS
+# include "ins_goons.h"
+# endif
+
+# ifdef CLASSIC_INSULTS
+# include "ins_classic.h"
+# endif
+
+# ifdef CSOPS_INSULTS
+# include "ins_csops.h"
+# endif
+
+ (char *) 0
+
+};
+
+/*
+ * How may I insult you? Let me count the ways...
+ */
+#define NOFINSULTS (sizeof(insults) / sizeof(insults[0]) - 1)
+
+/*
+ * return a pseudo-random insult.
+ */
+#define INSULT (insults[time(NULL) % NOFINSULTS])
+
+#endif /* USE_INSULTS */
+
+#endif /* _SUDO_INSULTS_H */
diff --git a/gnu/usr.bin/sudo/sudo/interfaces.c b/gnu/usr.bin/sudo/sudo/interfaces.c
new file mode 100644
index 00000000000..a2a12773150
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/interfaces.c
@@ -0,0 +1,264 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ *******************************************************************
+ *
+ * This module contains load_interfaces() a function that
+ * fills the interfaces global with a list of active ip
+ * addresses and their associated netmasks.
+ *
+ * Todd C. Miller Mon May 1 20:48:43 MDT 1995
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: interfaces.c,v 1.1 1996/10/14 05:14:49 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+#include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#include <netdb.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#else
+#include <sys/ioctl.h>
+#endif /* HAVE_SYS_SOCKIO_H */
+#ifdef _ISC
+#include <sys/stream.h>
+#include <sys/sioctl.h>
+#include <sys/stropts.h>
+#include <net/errno.h>
+#define STRSET(cmd, param, len) {strioctl.ic_cmd=(cmd);\
+ strioctl.ic_dp=(param);\
+ strioctl.ic_timout=0;\
+ strioctl.ic_len=(len);}
+#endif /* _ISC */
+#ifdef _MIPS
+#include <net/soioctl.h>
+#endif /* _MIPS */
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <net/if.h>
+
+#include "sudo.h"
+#include <options.h>
+#include "version.h"
+
+#if !defined(STDC_HEADERS) && !defined(__GNUC__)
+extern char *malloc __P((size_t));
+#endif /* !STDC_HEADERS && !__GNUC__ */
+
+/*
+ * Globals
+ */
+struct interface *interfaces;
+int num_interfaces = 0;
+extern int Argc;
+extern char **Argv;
+
+
+#if defined(SIOCGIFCONF) && !defined(STUB_LOAD_INTERFACES)
+/**********************************************************************
+ *
+ * load_interfaces()
+ *
+ * This function sets the interfaces global variable
+ * and sets the constituent ip addrs and netmasks.
+ */
+
+void load_interfaces()
+{
+ struct ifconf *ifconf;
+ char ifconf_buf[sizeof(struct ifconf) + BUFSIZ];
+ struct ifreq ifreq, *ifr;
+ struct sockaddr_in *sin;
+ unsigned long localhost_mask;
+ int sock, n, i;
+#ifdef _ISC
+ struct strioctl strioctl;
+#endif /* _ISC */
+
+ /* so we can skip localhost and its ilk */
+ localhost_mask = inet_addr("127.0.0.0");
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ /*
+ * get interface configuration or return (leaving interfaces NULL)
+ */
+ ifconf = (struct ifconf *) ifconf_buf;
+ ifconf->ifc_buf = (caddr_t) (ifconf_buf + sizeof(struct ifconf));
+ ifconf->ifc_len = sizeof(ifconf_buf) - sizeof(struct ifconf);
+
+ /* networking may not be installed in kernel */
+#ifdef _ISC
+ STRSET(SIOCGIFCONF, (caddr_t) ifconf, sizeof(ifconf_buf));
+ if (ioctl(sock, I_STR, (caddr_t) &strioctl) < 0)
+#else
+ if (ioctl(sock, SIOCGIFCONF, (caddr_t) ifconf) < 0)
+#endif /* _ISC */
+ return;
+
+ /*
+ * get the maximum number of interfaces that *could* exist.
+ */
+ n = ifconf->ifc_len / sizeof(struct ifreq);
+
+ /*
+ * malloc() space for interfaces array
+ */
+ interfaces = (struct interface *) malloc(sizeof(struct interface) * n);
+ if (interfaces == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ /*
+ * for each interface, get the ip address and netmask
+ */
+ for (ifreq.ifr_name[0] = '\0', i = 0; i < ifconf->ifc_len; ) {
+ /* get a pointer to the current interface */
+ ifr = (struct ifreq *) ((caddr_t) ifconf->ifc_req + i);
+
+ /* set i to the subscript of the next interface */
+#ifdef HAVE_SA_LEN
+ if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))
+ i += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
+ else
+#endif /* HAVE_SA_LEN */
+ i += sizeof(struct ifreq);
+
+ /* skip duplicates and interfaces with NULL addresses */
+ sin = (struct sockaddr_in *) &ifr->ifr_addr;
+ if (sin->sin_addr.s_addr == 0 ||
+ strncmp(ifr->ifr_name, ifreq.ifr_name, sizeof(ifr->ifr_name)) == 0)
+ continue;
+
+ /* make a working copy... */
+ ifreq = *ifr;
+
+ /* get the ip address */
+#ifdef _ISC
+ STRSET(SIOCGIFADDR, (caddr_t) &ifreq, sizeof(ifreq));
+ if (ioctl(sock, I_STR, (caddr_t) &strioctl) < 0) {
+#else
+ if (ioctl(sock, SIOCGIFADDR, (caddr_t) &ifreq)) {
+#endif /* _ISC */
+ /* non-fatal error if interface is down or not supported */
+ if (errno == EADDRNOTAVAIL || errno == ENXIO || errno == EAFNOSUPPORT)
+ continue;
+
+ (void) fprintf(stderr, "%s: Error, ioctl: SIOCGIFADDR ", Argv[0]);
+ perror("");
+ exit(1);
+ }
+ sin = (struct sockaddr_in *) &ifreq.ifr_addr;
+
+ /* store the ip address */
+ interfaces[num_interfaces].addr.s_addr = sin->sin_addr.s_addr;
+
+ /* get the netmask */
+#ifdef SIOCGIFNETMASK
+#ifdef _ISC
+ STRSET(SIOCGIFNETMASK, (caddr_t) &ifreq, sizeof(ifreq));
+ if (ioctl(sock, I_STR, (caddr_t) &strioctl) == 0) {
+#else
+ if (ioctl(sock, SIOCGIFNETMASK, (caddr_t) &ifreq) == 0) {
+#endif /* _ISC */
+ sin = (struct sockaddr_in *) &ifreq.ifr_addr;
+
+ /* store the netmask */
+ interfaces[num_interfaces].netmask.s_addr = sin->sin_addr.s_addr;
+ } else {
+#else
+ {
+#endif /* SIOCGIFNETMASK */
+ if (IN_CLASSC(interfaces[num_interfaces].addr.s_addr))
+ interfaces[num_interfaces].netmask.s_addr = htonl(IN_CLASSC_NET);
+ else if (IN_CLASSB(interfaces[num_interfaces].addr.s_addr))
+ interfaces[num_interfaces].netmask.s_addr = htonl(IN_CLASSB_NET);
+ else
+ interfaces[num_interfaces].netmask.s_addr = htonl(IN_CLASSA_NET);
+ }
+
+ /* avoid localhost and friends */
+ if ((interfaces[num_interfaces].addr.s_addr &
+ interfaces[num_interfaces].netmask.s_addr) == localhost_mask)
+ continue;
+
+ num_interfaces++;
+ }
+
+ /* if there were bogus entries, realloc the array */
+ if (n != num_interfaces) {
+ /* it is unlikely that num_interfaces will be 0 but who knows... */
+ if (num_interfaces != 0) {
+ interfaces = (struct interface *) realloc(interfaces,
+ sizeof(struct interface) * num_interfaces);
+ if (interfaces == NULL) {
+ perror("realloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ } else {
+ (void) free(interfaces);
+ }
+ }
+}
+
+#else /* !SIOCGIFCONF || STUB_LOAD_INTERFACES */
+
+/**********************************************************************
+ *
+ * load_interfaces()
+ *
+ * Stub function for those without SIOCGIFCONF
+ */
+
+void load_interfaces()
+{
+ return;
+}
+
+#endif /* SIOCGIFCONF && !STUB_LOAD_INTERFACES */
diff --git a/gnu/usr.bin/sudo/sudo/logging.c b/gnu/usr.bin/sudo/sudo/logging.c
new file mode 100644
index 00000000000..85cc707a80a
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/logging.c
@@ -0,0 +1,709 @@
+/*
+ * CU sudo version 1.5.2 (based on Root Group sudo version 1.1)
+ *
+ * This software comes with no waranty whatsoever, use at your own risk.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ */
+
+/*
+ * sudo version 1.1 allows users to execute commands as root
+ * Copyright (C) 1991 The Root Group, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************
+ *
+ * logging.c
+ *
+ * this file supports the general logging facilities
+ * if you want to change any error messages, this is probably
+ * the place to be...
+ *
+ * Jeff Nieusma Thu Mar 21 23:39:04 MST 1991
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: logging.c,v 1.1 1996/10/14 05:14:50 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+#include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#include <pwd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/errno.h>
+#include <netinet/in.h>
+
+#include "sudo.h"
+#include <options.h>
+
+/*
+ * Prototypes for local functions
+ */
+static void send_mail __P((void));
+static RETSIGTYPE reapchild __P((int));
+static int appropriate __P((int));
+#ifdef BROKEN_SYSLOG
+static void syslog_wrapper __P((int, char *, char *, char *));
+#endif /* BROKEN_SYSLOG */
+
+/*
+ * Globals
+ */
+static char *logline;
+extern int errorlineno;
+
+/*
+ * length of syslog-like header info used for mail and file logs
+ * is len("Mon MM HH:MM:SS : username : ")
+ */
+#define LOG_HEADER_LEN 29
+
+#ifdef BROKEN_SYSLOG
+#define MAXSYSLOGTRIES 16 /* num of retries for broken syslogs */
+#define SYSLOG(a,b,c,d) syslog_wrapper(a,b,c,d)
+
+/****************************************************************
+ *
+ * syslog_wrapper()
+ *
+ * This function logs via syslog w/ a priority and 3 strings args.
+ * It really shouldn't be necesary but some syslog()'s don't
+ * guarantee that the syslog() operation will succeed!
+ */
+
+static void syslog_wrapper(pri, fmt, arg1, arg2)
+ int pri;
+ char *fmt;
+ char *arg1;
+ char *arg2;
+{
+ int i;
+
+ for (i = 0; i < MAXSYSLOGTRIES; i++)
+ if (syslog(pri, fmt, arg1, arg2) == 0)
+ break;
+}
+#else
+#define SYSLOG(a,b,c,d) syslog(a,b,c,d)
+#endif /* BROKEN_SYSLOG */
+
+
+
+/**********************************************************************
+ *
+ * log_error()
+ *
+ * This function attempts to deliver mail to ALERTMAIL and either
+ * syslogs the error or writes it to the log file
+ */
+
+void log_error(code)
+ int code;
+{
+ char *p;
+ int count;
+ time_t now;
+#if (LOGGING & SLOG_FILE)
+ mode_t oldmask;
+ FILE *fp;
+#endif /* LOGGING & SLOG_FILE */
+#if (LOGGING & SLOG_SYSLOG)
+ int pri = Syslog_priority_NO; /* syslog priority, assume the worst */
+ char *tmp, save;
+#endif /* LOGGING & SLOG_SYSLOG */
+
+ /*
+ * Allocate enough memory for logline so we won't overflow it
+ */
+ count = LOG_HEADER_LEN + 136 + 2 * MAXPATHLEN + strlen(tty) + strlen(cwd) +
+ strlen(runas_user);
+ if (cmnd_args)
+ count += strlen(cmnd_args);
+
+ logline = (char *) malloc(count);
+ if (logline == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ /*
+ * we will skip this stuff when using syslog(3) but it is
+ * necesary for mail and file logs.
+ */
+ now = time((time_t) 0);
+ p = ctime(&now) + 4;
+ (void) sprintf(logline, "%15.15s : %8.8s : ", p, user_name);
+
+ /*
+ * we need a pointer to the end of logline for cheap appends.
+ */
+ p = logline + LOG_HEADER_LEN;
+
+ switch (code) {
+
+ case ALL_SYSTEMS_GO:
+ (void) sprintf(p, "TTY=%s ; PWD=%s ; USER=%s ; COMMAND=",
+ tty, cwd, runas_user);
+#if (LOGGING & SLOG_SYSLOG)
+ pri = Syslog_priority_OK;
+#endif /* LOGGING & SLOG_SYSLOG */
+ break;
+
+ case VALIDATE_NO_USER:
+ (void) sprintf(p,
+ "user NOT in sudoers ; TTY=%s ; PWD=%s ; USER=%s ; COMMAND=",
+ tty, cwd, runas_user);
+ break;
+
+ case VALIDATE_NOT_OK:
+ (void) sprintf(p,
+ "command not allowed ; TTY=%s ; PWD=%s ; USER=%s ; COMMAND=",
+ tty, cwd, runas_user);
+ break;
+
+ case VALIDATE_ERROR:
+ (void) sprintf(p, "error in %s, line %d ; TTY=%s ; PWD=%s ; USER=%s. ",
+ _PATH_SUDO_SUDOERS, errorlineno, tty, cwd, runas_user);
+ break;
+
+ case GLOBAL_NO_PW_ENT:
+ (void) sprintf(p,
+ "There is no passwd entry for uid %ld (TTY=%s). ",
+ (long) user_uid, tty);
+ break;
+
+ case PASSWORD_NOT_CORRECT:
+ (void) sprintf(p,
+ "password incorrect ; TTY=%s ; PWD=%s ; USER=%s ; COMMAND=",
+ tty, cwd, runas_user);
+ break;
+
+ case PASSWORDS_NOT_CORRECT:
+ (void) sprintf(p,
+ "%d incorrect passwords ; TTY=%s ; PWD=%s ; USER=%s ; COMMAND=",
+ TRIES_FOR_PASSWORD, tty, cwd, runas_user);
+ break;
+
+ case GLOBAL_NO_HOSTNAME:
+ strcat(p, "This machine does not have a hostname ");
+ break;
+
+ case NO_SUDOERS_FILE:
+ switch (errno) {
+ case ENOENT:
+ (void) sprintf(p, "There is no %s file. ",
+ _PATH_SUDO_SUDOERS);
+ break;
+ case EACCES:
+ (void) sprintf(p, "Can't read %s. ", _PATH_SUDO_SUDOERS);
+ break;
+ default:
+ (void) sprintf(p, "There is a problem opening %s ",
+ _PATH_SUDO_SUDOERS);
+ break;
+ }
+ break;
+
+ case GLOBAL_HOST_UNREGISTERED:
+ (void) sprintf(p, "gethostbyname() cannot find host %s ", host);
+ break;
+
+ case SUDOERS_NOT_FILE:
+ (void) sprintf(p, "%s is not a regular file ", _PATH_SUDO_SUDOERS);
+ break;
+
+ case SUDOERS_WRONG_OWNER:
+ (void) sprintf(p, "%s is not owned by uid %d and gid %d ",
+ _PATH_SUDO_SUDOERS, SUDOERS_UID, SUDOERS_GID);
+ break;
+
+ case SUDOERS_WRONG_MODE:
+ (void) sprintf(p, "%s is not mode %o ", _PATH_SUDO_SUDOERS,
+ SUDOERS_MODE);
+ break;
+
+ case SPOOF_ATTEMPT:
+ (void) sprintf(p,
+ "probable spoofing attempt; TTY=%s ; PWD=%s ; USER=%s ; COMMAND=",
+ tty, cwd, runas_user);
+ break;
+
+ case BAD_STAMPDIR:
+ (void) sprintf(p,
+ "%s owned by non-root or not mode 0700; TTY=%s ; PWD=%s ; USER=%s ; COMMAND=",
+ _PATH_SUDO_TIMEDIR, tty, cwd, runas_user);
+ break;
+
+ case BAD_STAMPFILE:
+ (void) sprintf(p,
+ "preposterous stampfile date; TTY=%s ; PWD=%s ; USER=%s ; COMMAND=",
+ tty, cwd, runas_user);
+ break;
+
+ default:
+ strcat(p, "found a wierd error : ");
+ break;
+ }
+
+
+ /*
+ * If this is a parse error or if the error is from load_globals()
+ * don't put argv in the message.
+ */
+ if (code != VALIDATE_ERROR && !(code & GLOBAL_PROBLEM)) {
+
+ /* stuff the command into the logline */
+ p = logline + strlen(logline);
+ strcpy(p, cmnd);
+
+ /* add a trailing space */
+ p += strlen(cmnd);
+ *p++ = ' ';
+ *p = '\0';
+
+ /* cat on command args if they exist */
+ if (cmnd_args) {
+ (void) strcpy(p, cmnd_args);
+ p += strlen(cmnd_args);
+ *p++ = ' ';
+ *p = '\0';
+ }
+ }
+
+#if (LOGGING & SLOG_SYSLOG)
+#ifdef Syslog_facility
+ openlog(Syslog_ident, Syslog_options, Syslog_facility);
+#else
+ openlog(Syslog_ident, Syslog_options);
+#endif /* Syslog_facility */
+
+ /*
+ * Log the full line, breaking into multiple syslog(3) calls if necesary
+ */
+ p = &logline[LOG_HEADER_LEN]; /* skip past the date and user */
+ for (count = 0; count < strlen(logline) / MAXSYSLOGLEN + 1; count++) {
+ if (strlen(p) > MAXSYSLOGLEN) {
+ /*
+ * Break up the line into what will fit on one syslog(3) line
+ * Try to break on a word boundary if possible.
+ */
+ for (tmp = p + MAXSYSLOGLEN; tmp > p && *tmp != ' '; tmp--)
+ ;
+ if (tmp <= p)
+ tmp = p + MAXSYSLOGLEN;
+
+ /* NULL terminate line, but save the char to restore later */
+ save = *tmp;
+ *tmp = '\0';
+
+ if (count == 0)
+ SYSLOG(pri, "%8.8s : %s", user_name, p);
+ else
+ SYSLOG(pri, "%8.8s : (command continued) %s", user_name, p);
+
+ *tmp = save; /* restore saved character */
+
+ /* eliminate leading whitespace */
+ for (p=tmp; *p != ' '; p++)
+ ;
+ } else {
+ if (count == 0)
+ SYSLOG(pri, "%8.8s : %s", user_name, p);
+ else
+ SYSLOG(pri, "%8.8s : (command continued) %s", user_name, p);
+ }
+ }
+ closelog();
+#endif /* LOGGING & SLOG_SYSLOG */
+#if (LOGGING & SLOG_FILE)
+
+ /* become root */
+ set_perms(PERM_ROOT, 0);
+
+ oldmask = umask(077);
+ fp = fopen(_PATH_SUDO_LOGFILE, "a");
+ (void) umask(oldmask);
+ if (fp == NULL) {
+ (void) sprintf(logline, "Can\'t open log file: %s", _PATH_SUDO_LOGFILE);
+ send_mail();
+ } else {
+ char *beg, *oldend, *end;
+ int maxlen = MAXLOGFILELEN;
+
+ /*
+ * Print out logline with word wrap
+ */
+ beg = end = logline;
+ while (beg) {
+ oldend = end;
+ end = strchr(oldend, ' ');
+
+ if (end) {
+ *end = '\0';
+ if (strlen(beg) > maxlen) {
+ /* too far, need to back up & print the line */
+
+ if (beg == (char *)logline)
+ maxlen -= 4; /* don't indent first line */
+
+ *end = ' ';
+ if (oldend != beg) {
+ /* rewind & print */
+ end = oldend-1;
+ while (*end == ' ')
+ --end;
+ *(++end) = '\0';
+ (void) fprintf(fp, "%s\n ", beg);
+ *end = ' ';
+ } else {
+ (void) fprintf(fp, "%s\n ", beg);
+ }
+
+ /* reset beg to point to the start of the new substring */
+ beg = end;
+ while (*beg == ' ')
+ ++beg;
+ } else {
+ /* we still have room */
+ *end = ' ';
+ }
+
+ /* remove leading whitespace */
+ while (*end == ' ')
+ ++end;
+ } else {
+ /* final line */
+ (void) fprintf(fp, "%s\n", beg);
+ beg = NULL; /* exit condition */
+ }
+ }
+
+ (void) fclose(fp);
+ }
+
+ /* relinquish root */
+ set_perms(PERM_USER, 0);
+#endif /* LOGGING & SLOG_FILE */
+
+ /* send mail if appropriate */
+ if (appropriate(code))
+ send_mail();
+}
+
+
+
+#ifdef MAILER
+/**********************************************************************
+ *
+ * send_mail()
+ *
+ * This function attempts to mail to ALERTMAIL about the sudo error
+ *
+ */
+
+static char *mail_argv[] = { "sendmail", "-t", (char *) NULL };
+
+static void send_mail()
+{
+ char *mailer = MAILER;
+ char *subject = MAILSUBJECT;
+ int fd[2];
+#ifdef POSIX_SIGNALS
+ struct sigaction action;
+
+ (void) memset((VOID *)&action, 0, sizeof(action));
+#endif /* POSIX_SIGNALS */
+
+ /* catch children as they die */
+#ifdef POSIX_SIGNALS
+ action.sa_handler = reapchild;
+ (void) sigaction(SIGCHLD, &action, NULL);
+#else
+ (void) signal(SIGCHLD, reapchild);
+#endif /* POSIX_SIGNALS */
+
+ if (fork())
+ return;
+
+ /*
+ * we don't want any security problems ...
+ */
+ set_perms(PERM_FULL_USER, 0);
+
+#ifdef POSIX_SIGNALS
+ action.sa_handler = SIG_IGN;
+ (void) sigaction(SIGHUP, &action, NULL);
+ (void) sigaction(SIGINT, &action, NULL);
+ (void) sigaction(SIGQUIT, &action, NULL);
+#else
+ (void) signal(SIGHUP, SIG_IGN);
+ (void) signal(SIGINT, SIG_IGN);
+ (void) signal(SIGQUIT, SIG_IGN);
+#endif /* POSIX_SIGNALS */
+
+ if (pipe(fd)) {
+ perror("send_mail: pipe");
+ exit(1);
+ }
+ (void) dup2(fd[0], 0);
+ (void) dup2(fd[1], 1);
+ (void) close(fd[0]);
+ (void) close(fd[1]);
+
+ if (!fork()) { /* child */
+ (void) close(1);
+ EXEC(mailer, mail_argv);
+
+ /* this should not happen */
+ perror(mailer);
+ exit(1);
+ } else { /* parent */
+ (void) close(0);
+
+ /* feed the data to sendmail */
+ /* XXX - do we need to fdopen this fd #1 to a new stream??? */
+ (void) fprintf(stdout, "To: %s\nSubject: %s\n\n%s : %s\n\n",
+ ALERTMAIL, subject, host, logline);
+ fclose(stdout);
+
+ exit(0);
+ }
+}
+#else
+static void send_mail()
+{
+ /* no mailer defined */
+ return;
+}
+#endif /* MAILER */
+
+
+
+/****************************************************************
+ *
+ * reapchild()
+ *
+ * This function gets rid of all the ugly zombies
+ */
+
+static RETSIGTYPE reapchild(sig)
+ int sig;
+{
+ (void) wait(NULL);
+#ifndef POSIX_SIGNALS
+ (void) signal(SIGCHLD, reapchild);
+#endif /* POSIX_SIGNALS */
+}
+
+
+
+/**********************************************************************
+ *
+ * inform_user ()
+ *
+ * This function lets the user know what is happening
+ * when an error occurs
+ */
+
+void inform_user(code)
+ int code;
+{
+ switch (code) {
+ case VALIDATE_NO_USER:
+ (void) fprintf(stderr,
+ "%s is not in the sudoers file. This incident will be reported.\n\n",
+ user_name);
+ break;
+
+ case VALIDATE_NOT_OK:
+ (void) fprintf(stderr,
+ "Sorry, user %s is not allowed to execute \"%s",
+ user_name, cmnd);
+
+ /* print command args if they exist */
+ if (cmnd_args) {
+ fputc(' ', stderr);
+ fputs(cmnd_args, stderr);
+ }
+
+ (void) fprintf(stderr, "\" as %s on %s.\n\n", runas_user, host);
+ break;
+
+ case VALIDATE_ERROR:
+ (void) fprintf(stderr,
+ "Sorry, there is a fatal error in the sudoers file.\n\n");
+ break;
+
+ case GLOBAL_NO_PW_ENT:
+ (void) fprintf(stderr,
+ "Intruder Alert! You don't exist in the passwd file\n\n");
+ break;
+
+ case GLOBAL_NO_SPW_ENT:
+ (void) fprintf(stderr,
+ "Intruder Alert! You don't exist in the shadow passwd file\n\n");
+ break;
+
+ case GLOBAL_NO_HOSTNAME:
+ (void) fprintf(stderr,
+ "This machine does not have a hostname\n\n");
+ break;
+
+ case GLOBAL_HOST_UNREGISTERED:
+ (void) fprintf(stderr,
+ "This machine is not available via gethostbyname()\n\n");
+ break;
+
+ case PASSWORD_NOT_CORRECT:
+ (void) fprintf(stderr, "Password not entered correctly\n\n");
+ break;
+
+ case PASSWORDS_NOT_CORRECT:
+ (void) fprintf(stderr, "Password not entered correctly after %d tries\n\n",
+ TRIES_FOR_PASSWORD);
+ break;
+
+ case NO_SUDOERS_FILE:
+ switch (errno) {
+ case ENOENT:
+ (void) fprintf(stderr, "There is no %s file.\n",
+ _PATH_SUDO_SUDOERS);
+ break;
+ default:
+ (void) fprintf(stderr, "Can't read %s: ",
+ _PATH_SUDO_SUDOERS);
+ perror("");
+ break;
+ }
+ break;
+
+ case SUDOERS_NOT_FILE:
+ (void) fprintf(stderr,
+ "%s is not a regular file!\n", _PATH_SUDO_SUDOERS);
+ break;
+
+ case SUDOERS_WRONG_OWNER:
+ (void) fprintf(stderr, "%s is not owned by uid %d and gid %d!\n",
+ _PATH_SUDO_SUDOERS, SUDOERS_UID, SUDOERS_GID);
+ break;
+
+ case SUDOERS_WRONG_MODE:
+ (void) fprintf(stderr, "%s must be mode %o!\n", _PATH_SUDO_SUDOERS,
+ SUDOERS_MODE);
+ break;
+
+ case SPOOF_ATTEMPT:
+ (void) fprintf(stderr,
+ "%s is not the same command that was validated, disallowing.\n",
+ cmnd);
+ break;
+
+ case BAD_STAMPDIR:
+ (void) fprintf(stderr,
+ "Timestamp directory has wrong permissions, ignoring.\n");
+ break;
+
+ case BAD_STAMPFILE:
+ (void) fprintf(stderr,
+ "Your timestamp file has a preposterous date, ignoring.\n");
+ break;
+
+ default:
+ (void) fprintf(stderr,
+ "Something wierd happened.\n\n");
+ break;
+ }
+}
+
+
+
+/****************************************************************
+ *
+ * appropriate()
+ *
+ * This function determines whether to send mail or not...
+ */
+
+static int appropriate(code)
+ int code;
+{
+
+ switch (code) {
+
+ /*
+ * these will NOT send mail
+ */
+ case VALIDATE_OK:
+ case VALIDATE_OK_NOPASS:
+ case PASSWORD_NOT_CORRECT:
+ case PASSWORDS_NOT_CORRECT:
+/* case ALL_SYSTEMS_GO: this is the same as OK */
+ return (0);
+ break;
+
+ case VALIDATE_NO_USER:
+#ifdef SEND_MAIL_WHEN_NO_USER
+ return (1);
+#else
+ return (0);
+#endif
+ break;
+
+ case VALIDATE_NOT_OK:
+#ifdef SEND_MAIL_WHEN_NOT_OK
+ return (1);
+#else
+ return (0);
+#endif
+ break;
+
+ /*
+ * these WILL send mail
+ */
+ case VALIDATE_ERROR:
+ case NO_SUDOERS_FILE:
+ case SPOOF_ATTEMPT:
+ case BAD_STAMPDIR:
+ case BAD_STAMPFILE:
+ default:
+ return (1);
+ break;
+
+ }
+}
diff --git a/gnu/usr.bin/sudo/sudo/options.h b/gnu/usr.bin/sudo/sudo/options.h
new file mode 100644
index 00000000000..47b7ceb3ea5
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/options.h
@@ -0,0 +1,110 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ * $Id: options.h,v 1.1 1996/10/14 05:14:50 millert Exp $
+ */
+
+#ifndef _SUDO_OPTIONS_H
+#define _SUDO_OPTIONS_H
+
+/*
+ * DANGER DANGER DANGER!
+ * Before you change anything here read through the OPTIONS file
+ * for a description of what this stuff does.
+ */
+
+/* User-configurable Sudo runtime options */
+
+/*#define FQDN /* expect fully qualified hosts in sudoers */
+#define LOGGING SLOG_SYSLOG /* log via SLOG_SYSLOG, SLOG_FILE, SLOG_BOTH */
+#define LOGFAC LOG_LOCAL2 /* syslog facility for sudo to use */
+#define MAXLOGFILELEN 80 /* max chars per log line (for line wrapping) */
+/*#define NO_ROOT_SUDO /* root is not allowed to use sudo */
+#define ALERTMAIL "root" /* user that gets sudo mail */
+#define SEND_MAIL_WHEN_NO_USER /* send mail when user not in sudoers file */
+/*#define SEND_MAIL_WHEN_NOT_OK /* send mail if no permissions to run command */
+/*#define EXEMPTGROUP "sudo" /* no passwd needed for users in this group */
+#define ENV_EDITOR /* visudo honors EDITOR and VISUAL envars */
+#define SHORT_MESSAGE /* short sudo message, no copyright printed */
+/*#define NO_MESSAGE /* no sudo "lecture" message */
+#define TIMEOUT 5 /* minutes before sudo asks for passwd again */
+#define PASSWORD_TIMEOUT 0 /* passwd prompt timeout (in minutes) */
+#define TRIES_FOR_PASSWORD 3 /* number of tries to enter passwd correctly */
+#define USE_INSULTS /* insult the user for incorrect passwords */
+#define CLASSIC_INSULTS /* sudo "classic" insults--need USE_INSULTS */
+/*#define HAL_INSULTS /* 2001-like insults--must define USE_INSULTS */
+/*#define GOONS_INSULTS /* Goon Show insults--must define USE_INSULTS */
+#define CSOPS_INSULTS /* CSOps insults--must define USE_INSULTS */
+#define EDITOR _PATH_VI /* default editor to use */
+#define MAILER _PATH_SENDMAIL /* what mailer to use */
+#define UMASK 0022 /* umask that the root-run prog should use */
+#define INCORRECT_PASSWORD "Sorry, try again." /* message for bad passwd */
+#define MAILSUBJECT "*** SECURITY information ***" /* subject of mail sent */
+#define PASSPROMPT "Password:" /* default password prompt */
+/*#define IGNORE_DOT_PATH /* ignore '.' in $PATH if it exists */
+/*#define SECURE_PATH "/bin:/usr/ucb:/usr/bin:/usr/etc:/etc" /* secure path */
+/*#define USE_EXECV /* use execv() instead of execvp() */
+/*#define SHELL_IF_NO_ARGS /* if sudo is given no arguments run a shell */
+/*#define SHELL_SETS_HOME /* -s sets $HOME to runas user's homedir */
+/*#define USE_TTY_TICKETS /* have a different ticket file for each tty */
+/*#define OTP_ONLY /* validate user via OTP (skey/opie) only */
+/*#define LONG_OTP_PROMPT /* use a two line OTP (skey/opie) prompt */
+#define FAST_MATCH /* command check fails if basenames not same */
+#ifndef SUDOERS_MODE
+#define SUDOERS_MODE 0440 /* file mode for sudoers (octal) */
+#endif /* SUDOERS_MODE */
+#ifndef SUDOERS_UID
+#define SUDOERS_UID 0 /* user id that owns sudoers (*not* a name) */
+#endif /* SUDOERS_UID */
+#ifndef SUDOERS_GID
+#define SUDOERS_GID 0 /* group id that owns sudoers (*not* a name) */
+#endif /* SUDOERS_GID */
+
+/********** You probably don't want to modify anything below here ***********/
+
+#ifdef USE_EXECV
+# define EXEC execv
+#else
+# define EXEC execvp
+#endif /* USE_EXECV */
+
+/*
+ * syslog(3) parameters
+ */
+
+#if (LOGGING & SLOG_SYSLOG)
+# include <syslog.h>
+# ifndef Syslog_ident
+# define Syslog_ident "sudo"
+# endif
+# ifndef Syslog_options
+# define Syslog_options 0
+# endif
+# if !defined(Syslog_facility) && defined(LOG_NFACILITIES)
+# define Syslog_facility LOGFAC
+# endif
+# ifndef Syslog_priority_OK
+# define Syslog_priority_OK LOG_NOTICE
+# endif
+# ifndef Syslog_priority_NO
+# define Syslog_priority_NO LOG_ALERT
+# endif
+#endif /* LOGGING & SLOG_SYSLOG */
+
+#endif /* _SUDO_OPTIONS_H */
diff --git a/gnu/usr.bin/sudo/sudo/parse.c b/gnu/usr.bin/sudo/sudo/parse.c
new file mode 100644
index 00000000000..1e09e3eacf9
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/parse.c
@@ -0,0 +1,446 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ *******************************************************************
+ *
+ * parse.c -- sudo parser frontend and comparison routines.
+ *
+ * Chris Jepeway <jepeway@cs.utk.edu>
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: parse.c,v 1.1 1996/10/14 05:14:51 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#if defined(HAVE_FNMATCH) && defined(HAVE_FNMATCH_H)
+# include <fnmatch.h>
+#else
+# ifndef HAVE_FNMATCH
+# include "emul/fnmatch.h"
+# endif /* HAVE_FNMATCH */
+#endif /* HAVE_FNMATCH_H */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+# include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#ifdef HAVE_NETGROUP_H
+# include <netgroup.h>
+#endif /* HAVE_NETGROUP_H */
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/stat.h>
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#include "sudo.h"
+#include <options.h>
+
+/*
+ * Globals
+ */
+int parse_error = FALSE;
+extern FILE *yyin, *yyout;
+extern int printmatches;
+
+/*
+ * Prototypes
+ */
+static int has_meta __P((char *));
+ void init_parser __P((void));
+
+/*
+ * This routine is called from the sudo.c module and tries to validate
+ * the user, host and command triplet.
+ */
+int validate(check_cmnd)
+ int check_cmnd;
+{
+ FILE *sudoers_fp;
+ int return_code;
+
+ /* become sudoers file owner */
+ set_perms(PERM_SUDOERS, 0);
+
+ if ((sudoers_fp = fopen(_PATH_SUDO_SUDOERS, "r")) == NULL) {
+ perror(_PATH_SUDO_SUDOERS);
+ log_error(NO_SUDOERS_FILE);
+ exit(1);
+ }
+ yyin = sudoers_fp;
+ yyout = stdout;
+
+ /*
+ * Allocate space for data structures in the parser.
+ */
+ init_parser();
+
+ /*
+ * Need to be root while stat'ing things in the parser.
+ */
+ set_perms(PERM_ROOT, 0);
+ return_code = yyparse();
+
+ /*
+ * Don't need to keep this open...
+ */
+ (void) fclose(sudoers_fp);
+
+ /* relinquish extra privs */
+ set_perms(PERM_USER, 0);
+
+ if (return_code || parse_error)
+ return(VALIDATE_ERROR);
+
+ /*
+ * Nothing on the top of the stack => user doesn't appear in sudoers.
+ * Allow anyone to try the psuedo commands "list" and "validate".
+ */
+ if (top == 0) {
+ if (check_cmnd == TRUE)
+ return(VALIDATE_NO_USER);
+ else
+ return(VALIDATE_NOT_OK);
+ }
+
+ /*
+ * Only check the actual command if the check_cmnd
+ * flag is set. It is not set for the "validate"
+ * and "list" pseudo-commands. Always check the
+ * host and user.
+ */
+ if (check_cmnd == FALSE)
+ while (top) {
+ if (host_matches == TRUE)
+ /* user may always do validate or list on allowed hosts */
+ if (no_passwd == TRUE)
+ return(VALIDATE_OK_NOPASS);
+ else
+ return(VALIDATE_OK);
+ top--;
+ }
+ else
+ while (top) {
+ if (host_matches == TRUE) {
+ if (cmnd_matches == TRUE) {
+ if (runas_matches == TRUE) {
+ /*
+ * User was granted access to cmnd on host.
+ * If no passwd required return as such.
+ */
+ if (no_passwd == TRUE)
+ return(VALIDATE_OK_NOPASS);
+ else
+ return(VALIDATE_OK);
+ }
+ } else if (cmnd_matches == FALSE) {
+ /* User was explicitly denied acces to cmnd on host. */
+ return(VALIDATE_NOT_OK);
+ }
+ }
+ top--;
+ }
+
+ /*
+ * we popped everything off the stack =>
+ * user was mentioned, but not explicitly
+ * granted nor denied access => say no
+ */
+ return(VALIDATE_NOT_OK);
+}
+
+
+
+/*
+ * If path doesn't end in /, return TRUE iff cmnd & path name the same inode;
+ * otherwise, return TRUE if cmnd names one of the inodes in path.
+ */
+int command_matches(cmnd, user_args, path, sudoers_args)
+ char *cmnd;
+ char *user_args;
+ char *path;
+ char *sudoers_args;
+{
+ int plen;
+ struct stat pst;
+ DIR *dirp;
+ struct dirent *dent;
+ char buf[MAXPATHLEN+1];
+ static char *c;
+
+ /* don't bother with pseudo commands like "validate" */
+ if (*cmnd != '/')
+ return(FALSE);
+
+ /* only need to stat cmnd once since it never changes */
+ if (cmnd_st.st_dev == 0) {
+ if (stat(cmnd, &cmnd_st) < 0)
+ return(FALSE);
+ if ((c = strrchr(cmnd, '/')) == NULL)
+ c = cmnd;
+ else
+ c++;
+ }
+
+ /*
+ * If the pathname has meta characters in it use fnmatch(3)
+ * to do the matching
+ */
+ if (has_meta(path)) {
+ /*
+ * Return true if fnmatch(3) succeeds and there are no args
+ * (in sudoers or command) or if the args match;
+ * else return false.
+ */
+ if (fnmatch(path, 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] != '/') {
+#ifdef FAST_MATCH
+ char *p;
+
+ /* Only proceed if the basenames of cmnd and path are the same */
+ if ((p = strrchr(path, '/')) == NULL)
+ p = path;
+ else
+ p++;
+ if (strcmp(c, p))
+ return(FALSE);
+#endif /* FAST_MATCH */
+
+ if (stat(path, &pst) < 0)
+ return(FALSE);
+
+ /*
+ * Return true if inode/device matches and there are no args
+ * (in sudoers or command) or if the args match;
+ * else return false.
+ */
+ if (cmnd_st.st_dev != pst.st_dev || cmnd_st.st_ino != pst.st_ino)
+ 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);
+ }
+
+ /*
+ * Grot through path's directory entries, looking for cmnd.
+ */
+ dirp = opendir(path);
+ if (dirp == NULL)
+ return(FALSE);
+
+ while ((dent = readdir(dirp)) != NULL) {
+ strcpy(buf, path);
+ strcat(buf, dent->d_name);
+#ifdef FAST_MATCH
+ /* only stat if basenames are not the same */
+ if (strcmp(c, dent->d_name))
+ continue;
+#endif /* FAST_MATCH */
+ if (stat(buf, &pst) < 0)
+ continue;
+ if (cmnd_st.st_dev == pst.st_dev && cmnd_st.st_ino == pst.st_ino)
+ break;
+ }
+
+ closedir(dirp);
+ return(dent != NULL);
+ }
+}
+
+
+
+/*
+ * 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;
+{
+ int i;
+ char *m;
+ struct in_addr addr, mask;
+
+ /* If there's an explicate netmask, use it. */
+ if ((m = strchr(n, '/'))) {
+ *m++ = '\0';
+ mask.s_addr = inet_addr(m);
+ addr.s_addr = inet_addr(n);
+ *(m - 1) = '/';
+
+ for (i = 0; i < num_interfaces; i++)
+ if ((interfaces[i].addr.s_addr & mask.s_addr) == addr.s_addr)
+ return(TRUE);
+ } else {
+ addr.s_addr = inet_addr(n);
+
+ for (i = 0; i < num_interfaces; i++)
+ if (interfaces[i].addr.s_addr == addr.s_addr ||
+ (interfaces[i].addr.s_addr & interfaces[i].netmask.s_addr)
+ == addr.s_addr)
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+
+
+/*
+ * Returns TRUE if the given user belongs to the named group,
+ * else returns FALSE.
+ */
+int usergr_matches(group, user)
+ char *group;
+ char *user;
+{
+ struct group *grpent;
+ char **cur;
+
+ /* make sure we have a valid usergroup, sudo style */
+ if (*group++ != '%')
+ return(FALSE);
+
+ if ((grpent = getgrnam(group)) == NULL)
+ return(FALSE);
+
+ /*
+ * Check against user's real gid as well as group's user list
+ */
+ if (grpent->gr_gid == user_gid)
+ return(TRUE);
+
+ for (cur=grpent->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" or "user" may be NULL
+ * in which case that argument is not checked...
+ */
+int netgr_matches(netgr, host, user)
+ char *netgr;
+ char *host;
+ char *user;
+{
+#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) {
+ if ((domain = (char *) malloc(MAXHOSTNAMELEN + 1)) == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ if (getdomainname(domain, MAXHOSTNAMELEN + 1) != 0 || *domain == '\0') {
+ (void) free(domain);
+ domain = NULL;
+ }
+ }
+#endif /* HAVE_GETDOMAINNAME */
+
+#ifdef HAVE_INNETGR
+ return(innetgr(netgr, host, user, domain));
+#else
+ return(FALSE);
+#endif /* HAVE_INNETGR */
+}
+
+
+
+/*
+ * Returns TRUE if "s" has shell meta characters in it,
+ * else returns FALSE.
+ */
+static int has_meta(s)
+ char *s;
+{
+ register char *t;
+
+ for (t = s; *t; t++) {
+ if (*t == '\\' || *t == '?' || *t == '*' || *t == '[' || *t == ']')
+ return(TRUE);
+ }
+ return(FALSE);
+}
diff --git a/gnu/usr.bin/sudo/sudo/parse.lex b/gnu/usr.bin/sudo/sudo/parse.lex
new file mode 100644
index 00000000000..b2b541a4909
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/parse.lex
@@ -0,0 +1,354 @@
+%{
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ *******************************************************************
+ *
+ * parse.lex -- lexigraphical analyzer for sudo.
+ *
+ * Chris Jepeway <jepeway@cs.utk.edu>
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: parse.lex,v 1.1 1996/10/14 05:14:51 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+#include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include "sudo.h"
+#include <options.h>
+#include "y.tab.h"
+
+#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 void fill __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 *));
+
+/* 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
+%}
+
+OCTET [[:digit:]]{1,3}
+DOTTEDQUAD {OCTET}(\.{OCTET}){3}
+WORD [[:alnum:]_-]+
+
+%e 4000
+%p 6000
+%k 3500
+
+%s GOTCMND
+%s GOTRUNAS
+
+%%
+[ \t]+ { /* throw away space/tabs */
+ sawspace = TRUE; /* but remember for fill_args */
+ }
+
+\\\n {
+ sawspace = TRUE; /* remember for fill_args */
+ ++sudolineno;
+ LEXTRACE("\n\t");
+ } /* throw away EOL after \ */
+
+<GOTCMND>\\[:\,=\\ \t] {
+ LEXTRACE("QUOTEDCHAR ");
+ fill_args(yytext + 1, 1, sawspace);
+ sawspace = FALSE;
+ }
+
+<GOTCMND>[:\,=\n] {
+ BEGIN INITIAL;
+ unput(*yytext);
+ return(COMMAND);
+ } /* end of command line args */
+
+\n {
+ ++sudolineno;
+ LEXTRACE("\n");
+ return(COMMENT);
+ } /* return newline */
+
+<INITIAL>#.*\n {
+ ++sudolineno;
+ LEXTRACE("\n");
+ return(COMMENT);
+ } /* return comments */
+
+<GOTCMND>[^:\,= \t\n]+ {
+ LEXTRACE("ARG ");
+ fill_args(yytext, yyleng, sawspace);
+ sawspace = FALSE;
+ } /* a command line arg */
+
+\, {
+ LEXTRACE(", ");
+ return(',');
+ } /* return ',' */
+
+\! {
+ return('!'); /* return '!' */
+ }
+
+= {
+ LEXTRACE("= ");
+ return('=');
+ } /* return '=' */
+
+: {
+ LEXTRACE(": ");
+ return(':');
+ } /* return ':' */
+
+\. {
+ return('.');
+ }
+
+NOPASSWD[[:blank:]]*: {
+ /* cmnd does not require passwd for this user */
+ LEXTRACE("NOPASSWD ");
+ return(NOPASSWD);
+ }
+
+\+{WORD} {
+ /* netgroup */
+ fill(yytext, yyleng);
+ return(NETGROUP);
+ }
+
+\%{WORD} {
+ /* UN*X group */
+ fill(yytext, yyleng);
+ return(USERGROUP);
+ }
+
+{DOTTEDQUAD}(\/{DOTTEDQUAD})? {
+ fill(yytext, yyleng);
+ LEXTRACE("NTWKADDR ");
+ return(NTWKADDR);
+ }
+
+[[:alpha:]][[:alnum:]_-]*(\.{WORD})+ {
+ fill(yytext, yyleng);
+ LEXTRACE("FQHOST ");
+ return(FQHOST);
+ }
+
+<INITIAL>\( {
+ BEGIN GOTRUNAS;
+ LEXTRACE("RUNAS ");
+ return (RUNAS);
+ }
+
+<GOTRUNAS>[[:upper:]][[:upper:][:digit:]_]* {
+ /* User_Alias that user can run command as or ALL */
+ fill(yytext, yyleng);
+ if (strcmp(yytext, "ALL") == 0) {
+ LEXTRACE("ALL ");
+ return(ALL);
+ } else {
+ LEXTRACE("ALIAS ");
+ return(ALIAS);
+ }
+ }
+
+<GOTRUNAS>#?{WORD} {
+ /* username/uid that user can run command as */
+ fill(yytext, yyleng);
+ LEXTRACE("NAME ");
+ return(NAME);
+ }
+
+<GOTRUNAS>\) BEGIN INITIAL;
+
+
+\/[^\,:=\\ \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 */
+
+[[:upper:]][[:upper:][:digit:]_]* {
+ fill(yytext, yyleng);
+ if (strcmp(yytext, "ALL") == 0) {
+ LEXTRACE("ALL ");
+ return(ALL);
+ }
+ LEXTRACE("ALIAS ");
+ return(ALIAS);
+ }
+
+[[:alnum:]][[:alnum:]_-]* {
+ int l;
+
+ fill(yytext, yyleng);
+ if (strcmp(yytext, "Host_Alias") == 0) {
+ LEXTRACE("HOSTALIAS ");
+ return(HOSTALIAS);
+ }
+ if (strcmp(yytext, "Cmnd_Alias") == 0) {
+ LEXTRACE("CMNDALIAS ");
+ return(CMNDALIAS);
+ }
+ if (strcmp(yytext, "User_Alias") == 0) {
+ LEXTRACE("USERALIAS ");
+ return(USERALIAS);
+ }
+ l = yyleng - 1;
+ if (isalpha(yytext[l]) || isdigit(yytext[l])) {
+ /* NAME is what RFC1034 calls a label */
+ LEXTRACE("NAME ");
+ return(NAME);
+ }
+
+ return(ERROR);
+ }
+
+. {
+ return(ERROR);
+ } /* parse error */
+
+%%
+static void fill(s, len)
+ char *s;
+ int len;
+{
+ yylval.string = (char *) malloc(len + 1);
+ if (yylval.string == NULL)
+ yyerror("unable to allocate memory");
+
+ /* copy the string and NULL-terminate it */
+ (void) strncpy(yylval.string, s, len);
+ yylval.string[len] = '\0';
+}
+
+
+static void fill_cmnd(s, len)
+ char *s;
+ int len;
+{
+ arg_len = arg_size = 0;
+
+ yylval.command.cmnd = (char *) malloc(len + 1);
+ if (yylval.command.cmnd == NULL)
+ yyerror("unable to allocate memory");
+
+ /* copy the string and NULL-terminate it */
+ (void) strncpy(yylval.command.cmnd, s, len);
+ yylval.command.cmnd[len] = '\0';
+
+ yylval.command.args = NULL;
+}
+
+
+static void fill_args(s, len, addspace)
+ char *s;
+ int len;
+ int addspace;
+{
+ int new_len;
+ char *p;
+
+ /*
+ * If first arg, malloc() some room, else if we don't
+ * have enough space realloc() some more.
+ */
+ if (yylval.command.args == NULL) {
+ addspace = 0;
+ new_len = len;
+
+ while (new_len >= (arg_size += COMMANDARGINC))
+ ;
+
+ yylval.command.args = (char *) malloc(arg_size);
+ if (yylval.command.args == NULL)
+ yyerror("unable to allocate memory");
+ } 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))
+ ;
+
+ yylval.command.args = (char *) realloc(yylval.command.args, arg_size);
+ if (yylval.command.args == NULL)
+ yyerror("unable to allocate memory");
+ }
+ }
+
+ /* Efficiently append the arg (with a leading space if needed). */
+ p = yylval.command.args + arg_len;
+ if (addspace)
+ *p++ = ' ';
+ (void) strcpy(p, s);
+ arg_len = new_len;
+}
+
+
+int yywrap()
+{
+#ifdef YY_NEW_FILE
+ YY_NEW_FILE;
+#endif /* YY_NEW_FILE */
+
+ /* don't reset the aliases if called by testsudoers */
+ if (clearaliases)
+ reset_aliases();
+
+ return(TRUE);
+}
diff --git a/gnu/usr.bin/sudo/sudo/parse.yacc b/gnu/usr.bin/sudo/sudo/parse.yacc
new file mode 100644
index 00000000000..4508a99a411
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/parse.yacc
@@ -0,0 +1,954 @@
+%{
+
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ *******************************************************************
+ *
+ * parse.yacc -- yacc parser and alias manipulation routines for sudo.
+ *
+ * Chris Jepeway <jepeway@cs.utk.edu>
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: parse.yacc,v 1.1 1996/10/14 05:14:52 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+#include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#ifdef HAVE_LSEARCH
+#include <search.h>
+#endif /* HAVE_LSEARCH */
+
+#include <options.h>
+#include "sudo.h"
+
+#ifndef HAVE_LSEARCH
+#include "emul/search.h"
+#endif /* HAVE_LSEARCH */
+
+#ifndef HAVE_STRCASECMP
+#define strcasecmp(a,b) strcmp(a,b)
+#endif /* !HAVE_STRCASECMP */
+
+/*
+ * Globals
+ */
+extern int sudolineno, parse_error;
+int errorlineno = -1;
+int clearaliases = 1;
+int printmatches = FALSE;
+
+/*
+ * Alias types
+ */
+#define HOST 1
+#define CMND 2
+#define USER 3
+
+/*
+ * The matching stack, initial space allocated in init_parser().
+ */
+struct matchstack *match;
+int top = 0, stacksize = 0;
+
+#define push \
+ { \
+ if (top > stacksize) { \
+ while ((stacksize += STACKINCREMENT) < top); \
+ match = (struct matchstack *) realloc(match, sizeof(struct matchstack) * stacksize); \
+ if (match == NULL) { \
+ perror("malloc"); \
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]); \
+ exit(1); \
+ } \
+ } \
+ match[top].user = -1; \
+ match[top].cmnd = -1; \
+ match[top].host = -1; \
+ match[top].runas = -1; \
+ match[top].nopass = -1; \
+ top++; \
+ }
+
+#define pop \
+ { \
+ if (top == 0) \
+ yyerror("matching stack underflow"); \
+ else \
+ top--; \
+ }
+
+/*
+ * 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 ca_list_len = 0, ca_list_size = 0;
+static struct command_alias *ca_list = NULL;
+
+/*
+ * Protoypes
+ */
+extern int command_matches __P((char *, char *, char *, char *));
+extern int addr_matches __P((char *));
+extern int netgr_matches __P((char *, char *, char *));
+extern int usergr_matches __P((char *, char *));
+static int find_alias __P((char *, int));
+static int add_alias __P((char *, int));
+static int more_aliases __P((size_t));
+static void append __P((char *, char **, size_t *, size_t *, int));
+static void expand_ca_list __P((void));
+static void expand_match_list __P((void));
+ void init_parser __P((void));
+ void yyerror __P((char *));
+
+void yyerror(s)
+ char *s;
+{
+ /* save the line the first error occured on */
+ if (errorlineno == -1)
+ errorlineno = sudolineno;
+#ifndef TRACELEXER
+ (void) fprintf(stderr, ">>> sudoers file: %s, line %d <<<\n", s, sudolineno);
+#else
+ (void) fprintf(stderr, "<*> ");
+#endif
+ parse_error = TRUE;
+}
+%}
+
+%union {
+ char *string;
+ int BOOLEAN;
+ struct sudo_command command;
+ int tok;
+}
+
+
+%start file /* special start symbol */
+%token <string> ALIAS /* an UPPERCASE alias name */
+%token <string> NTWKADDR /* w.x.y.z */
+%token <string> FQHOST /* foo.bar.com */
+%token <string> NETGROUP /* a netgroup (+NAME) */
+%token <string> USERGROUP /* a usergroup (%NAME) */
+%token <string> NAME /* a mixed-case name */
+%token <tok> RUNAS /* a mixed-case runas name */
+%token <tok> NOPASSWD /* no passwd req for command*/
+%token <command> COMMAND /* an absolute pathname */
+%token <tok> COMMENT /* comment and/or carriage return */
+%token <tok> ALL /* ALL keyword */
+%token <tok> HOSTALIAS /* Host_Alias keyword */
+%token <tok> CMNDALIAS /* Cmnd_Alias keyword */
+%token <tok> USERALIAS /* User_Alias keyword */
+%token <tok> ':' '=' ',' '!' '.' /* union member tokens */
+%token <tok> ERROR
+
+%type <BOOLEAN> cmnd
+%type <BOOLEAN> opcmnd
+%type <BOOLEAN> runasspec
+%type <BOOLEAN> runaslist
+%type <BOOLEAN> runasuser
+%type <BOOLEAN> nopasswd
+
+%%
+
+file : entry
+ | file entry
+ ;
+
+entry : COMMENT
+ { ; }
+ | error COMMENT
+ { yyerrok; }
+ | { push; } user privileges {
+ while (top && user_matches != TRUE) {
+ pop;
+ }
+ }
+ | USERALIAS useraliases
+ { ; }
+ | HOSTALIAS hostaliases
+ { ; }
+ | CMNDALIAS cmndaliases
+ { ; }
+ ;
+
+
+privileges : privilege
+ | privileges ':' privilege
+ ;
+
+privilege : hostspec '=' cmndspeclist {
+ if (user_matches == TRUE) {
+ push;
+ user_matches = TRUE;
+ } else {
+ no_passwd = -1;
+ runas_matches = -1;
+ }
+ }
+ ;
+
+hostspec : ALL {
+ host_matches = TRUE;
+ }
+ | NTWKADDR {
+ if (addr_matches($1))
+ host_matches = TRUE;
+ (void) free($1);
+ }
+ | NETGROUP {
+ if (netgr_matches($1, host, NULL))
+ host_matches = TRUE;
+ (void) free($1);
+ }
+ | NAME {
+ if (strcasecmp(shost, $1) == 0)
+ host_matches = TRUE;
+ (void) free($1);
+ }
+ | FQHOST {
+ if (strcasecmp(host, $1) == 0)
+ host_matches = TRUE;
+ (void) free($1);
+ }
+ | ALIAS {
+ /* could be an all-caps hostname */
+ if (find_alias($1, HOST) || !strcasecmp(shost, $1))
+ host_matches = TRUE;
+ (void) free($1);
+ }
+ ;
+
+cmndspeclist : cmndspec
+ | cmndspeclist ',' cmndspec
+ ;
+
+cmndspec : runasspec nopasswd opcmnd {
+ if ($1 > 0 && $3 == TRUE) {
+ runas_matches = TRUE;
+ if ($2 == TRUE)
+ no_passwd = TRUE;
+ } else if (printmatches == TRUE) {
+ cm_list[cm_list_len].runas_len = 0;
+ cm_list[cm_list_len].cmnd_len = 0;
+ cm_list[cm_list_len].nopasswd = FALSE;
+ }
+ }
+ ;
+
+opcmnd : cmnd { ; }
+ | '!' {
+ if (printmatches == TRUE && host_matches == TRUE &&
+ user_matches == TRUE) {
+ append("!", &cm_list[cm_list_len].cmnd,
+ &cm_list[cm_list_len].cmnd_len,
+ &cm_list[cm_list_len].cmnd_size, 0);
+ push;
+ user_matches = TRUE;
+ host_matches = TRUE;
+ } else {
+ push;
+ }
+ } opcmnd {
+ int cmnd_matched = cmnd_matches;
+ pop;
+ if (cmnd_matched == TRUE)
+ cmnd_matches = FALSE;
+ else if (cmnd_matched == FALSE)
+ cmnd_matches = TRUE;
+ $$ = cmnd_matches;
+ }
+ ;
+
+runasspec : /* empty */ {
+ $$ = (strcmp("root", runas_user) == 0);
+ }
+ | RUNAS runaslist {
+ $$ = $2;
+ }
+ ;
+
+runaslist : runasuser {
+ $$ = $1;
+ }
+ | runaslist ',' runasuser {
+ $$ = $1 + $3;
+ }
+ ;
+
+
+runasuser : NAME {
+ $$ = (strcmp($1, runas_user) == 0);
+ if (printmatches == TRUE && host_matches == TRUE &&
+ user_matches == TRUE)
+ append($1, &cm_list[cm_list_len].runas,
+ &cm_list[cm_list_len].runas_len,
+ &cm_list[cm_list_len].runas_size, ':');
+ (void) free($1);
+ }
+ | USERGROUP {
+ $$ = usergr_matches($1, runas_user);
+ if (printmatches == TRUE && host_matches == TRUE &&
+ user_matches == TRUE) {
+ append("%", &cm_list[cm_list_len].runas,
+ &cm_list[cm_list_len].runas_len,
+ &cm_list[cm_list_len].runas_size, ':');
+ append($1, &cm_list[cm_list_len].runas,
+ &cm_list[cm_list_len].runas_len,
+ &cm_list[cm_list_len].runas_size, 0);
+ }
+ (void) free($1);
+ }
+ | NETGROUP {
+ $$ = netgr_matches($1, NULL, runas_user);
+ if (printmatches == TRUE && host_matches == TRUE &&
+ user_matches == TRUE) {
+ append("+", &cm_list[cm_list_len].runas,
+ &cm_list[cm_list_len].runas_len,
+ &cm_list[cm_list_len].runas_size, ':');
+ append($1, &cm_list[cm_list_len].runas,
+ &cm_list[cm_list_len].runas_len,
+ &cm_list[cm_list_len].runas_size, 0);
+ }
+ (void) free($1);
+ }
+ | ALIAS {
+ /* could be an all-caps username */
+ if (find_alias($1, USER) || !strcmp($1, runas_user))
+ $$ = TRUE;
+ else
+ $$ = FALSE;
+ if (printmatches == TRUE && host_matches == TRUE &&
+ user_matches == TRUE)
+ append($1, &cm_list[cm_list_len].runas,
+ &cm_list[cm_list_len].runas_len,
+ &cm_list[cm_list_len].runas_size, ':');
+ (void) free($1);
+ }
+ | ALL {
+ $$ = TRUE;
+ if (printmatches == TRUE && host_matches == TRUE &&
+ user_matches == TRUE)
+ append("ALL", &cm_list[cm_list_len].runas,
+ &cm_list[cm_list_len].runas_len,
+ &cm_list[cm_list_len].runas_size, ':');
+ }
+ ;
+
+nopasswd : /* empty */ {
+ $$ = FALSE;
+ }
+ | NOPASSWD {
+ $$ = TRUE;
+ if (printmatches == TRUE && host_matches == TRUE &&
+ user_matches == TRUE)
+ cm_list[cm_list_len].nopasswd = TRUE;
+ }
+ ;
+
+cmnd : ALL {
+ if (printmatches == TRUE && in_alias == TRUE) {
+ append("ALL", &ca_list[ca_list_len-1].entries,
+ &ca_list[ca_list_len-1].entries_len,
+ &ca_list[ca_list_len-1].entries_size, ',');
+ }
+ if (printmatches == TRUE && host_matches == TRUE &&
+ user_matches == TRUE) {
+ append("ALL", &cm_list[cm_list_len].cmnd,
+ &cm_list[cm_list_len].cmnd_len,
+ &cm_list[cm_list_len].cmnd_size, 0);
+ expand_match_list();
+ }
+
+ cmnd_matches = TRUE;
+ $$ = TRUE;
+ }
+ | ALIAS {
+ if (printmatches == TRUE && in_alias == TRUE) {
+ append($1, &ca_list[ca_list_len-1].entries,
+ &ca_list[ca_list_len-1].entries_len,
+ &ca_list[ca_list_len-1].entries_size, ',');
+ }
+ if (printmatches == TRUE && host_matches == TRUE &&
+ user_matches == TRUE) {
+ append($1, &cm_list[cm_list_len].cmnd,
+ &cm_list[cm_list_len].cmnd_len,
+ &cm_list[cm_list_len].cmnd_size, 0);
+ expand_match_list();
+ }
+ if (find_alias($1, CMND)) {
+ cmnd_matches = TRUE;
+ $$ = TRUE;
+ }
+ (void) free($1);
+ }
+ | COMMAND {
+ if (printmatches == TRUE && in_alias == TRUE) {
+ append($1.cmnd, &ca_list[ca_list_len-1].entries,
+ &ca_list[ca_list_len-1].entries_len,
+ &ca_list[ca_list_len-1].entries_size, ',');
+ if ($1.args)
+ append($1.args, &ca_list[ca_list_len-1].entries,
+ &ca_list[ca_list_len-1].entries_len,
+ &ca_list[ca_list_len-1].entries_size, ' ');
+ }
+ if (printmatches == TRUE && host_matches == TRUE &&
+ user_matches == TRUE) {
+ append($1.cmnd, &cm_list[cm_list_len].cmnd,
+ &cm_list[cm_list_len].cmnd_len,
+ &cm_list[cm_list_len].cmnd_size, 0);
+ if ($1.args)
+ append($1.args, &cm_list[cm_list_len].cmnd,
+ &cm_list[cm_list_len].cmnd_len,
+ &cm_list[cm_list_len].cmnd_size, ' ');
+ expand_match_list();
+ }
+
+ /* if NewArgc > 1 pass ptr to 1st arg, else NULL */
+ if (command_matches(cmnd, (NewArgc > 1) ?
+ cmnd_args : NULL, $1.cmnd, $1.args)) {
+ cmnd_matches = TRUE;
+ $$ = TRUE;
+ }
+
+ (void) free($1.cmnd);
+ if ($1.args)
+ (void) free($1.args);
+ }
+ ;
+
+hostaliases : hostalias
+ | hostaliases ':' hostalias
+ ;
+
+hostalias : ALIAS { push; } '=' hostlist {
+ if (host_matches == TRUE && !add_alias($1, HOST))
+ YYERROR;
+ pop;
+ }
+ ;
+
+hostlist : hostspec
+ | hostlist ',' hostspec
+ ;
+
+cmndaliases : cmndalias
+ | cmndaliases ':' cmndalias
+ ;
+
+cmndalias : ALIAS {
+ push;
+ if (printmatches == TRUE) {
+ in_alias = TRUE;
+ /* Allocate space for ca_list if necesary. */
+ expand_ca_list();
+ if (!(ca_list[ca_list_len-1].alias = strdup($1))){
+ perror("malloc");
+ (void) fprintf(stderr,
+ "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ }
+ } '=' cmndlist {
+ if (cmnd_matches == TRUE && !add_alias($1, CMND))
+ YYERROR;
+ pop;
+ (void) free($1);
+
+ if (printmatches == TRUE)
+ in_alias = FALSE;
+ }
+ ;
+
+cmndlist : cmnd
+ { ; }
+ | cmndlist ',' cmnd
+ ;
+
+useraliases : useralias
+ | useraliases ':' useralias
+ ;
+
+useralias : ALIAS { push; } '=' userlist {
+ if (user_matches == TRUE && !add_alias($1, USER))
+ YYERROR;
+ pop;
+ (void) free($1);
+ }
+ ;
+
+userlist : user
+ { ; }
+ | userlist ',' user
+ ;
+
+user : NAME {
+ if (strcmp($1, user_name) == 0)
+ user_matches = TRUE;
+ (void) free($1);
+ }
+ | USERGROUP {
+ if (usergr_matches($1, user_name))
+ user_matches = TRUE;
+ (void) free($1);
+ }
+ | NETGROUP {
+ if (netgr_matches($1, NULL, user_name))
+ user_matches = TRUE;
+ (void) free($1);
+ }
+ | ALIAS {
+ /* could be an all-caps username */
+ if (find_alias($1, USER) || !strcmp($1, user_name))
+ user_matches = TRUE;
+ (void) free($1);
+ }
+ | ALL {
+ user_matches = TRUE;
+ }
+ ;
+
+%%
+
+
+typedef struct {
+ int type;
+ char name[BUFSIZ];
+} aliasinfo;
+
+#define MOREALIASES (32)
+aliasinfo *aliases = NULL;
+size_t naliases = 0;
+size_t nslots = 0;
+
+
+/**********************************************************************
+ *
+ * aliascmp()
+ *
+ * This function compares two aliasinfo structures.
+ */
+
+static int aliascmp(a1, a2)
+ const VOID *a1, *a2;
+{
+ int r;
+ aliasinfo *ai1, *ai2;
+
+ ai1 = (aliasinfo *) a1;
+ ai2 = (aliasinfo *) a2;
+ r = strcmp(ai1->name, ai2->name);
+ if (r == 0)
+ r = ai1->type - ai2->type;
+
+ return(r);
+}
+
+
+/**********************************************************************
+ *
+ * cmndaliascmp()
+ *
+ * This function compares two command_alias structures.
+ */
+
+static int cmndaliascmp(entry, key)
+ const VOID *entry, *key;
+{
+ struct command_alias *ca1 = (struct command_alias *) key;
+ struct command_alias *ca2 = (struct command_alias *) entry;
+
+ return(strcmp(ca1->alias, ca2->alias));
+}
+
+
+/**********************************************************************
+ *
+ * add_alias()
+ *
+ * This function adds the named alias of the specified type to the
+ * aliases list.
+ */
+
+static int add_alias(alias, type)
+ char *alias;
+ int type;
+{
+ aliasinfo ai, *aip;
+ char s[512];
+ int ok;
+
+ ok = FALSE; /* assume failure */
+ ai.type = type;
+ (void) strcpy(ai.name, alias);
+ if (lfind((VOID *)&ai, (VOID *)aliases, &naliases, sizeof(ai),
+ aliascmp) != NULL) {
+ (void) sprintf(s, "Alias `%s' already defined", alias);
+ yyerror(s);
+ } else {
+ if (naliases == nslots && !more_aliases(nslots)) {
+ (void) sprintf(s, "Out of memory defining alias `%s'", alias);
+ yyerror(s);
+ }
+
+ aip = (aliasinfo *) lsearch((VOID *)&ai, (VOID *)aliases,
+ &naliases, sizeof(ai), aliascmp);
+
+ if (aip != NULL) {
+ ok = TRUE;
+ } else {
+ (void) sprintf(s, "Aliases corrupted defining alias `%s'", alias);
+ yyerror(s);
+ }
+ }
+
+ return(ok);
+}
+
+
+/**********************************************************************
+ *
+ * find_alias()
+ *
+ * This function searches for the named alias of the specified type.
+ */
+
+static int find_alias(alias, type)
+ char *alias;
+ int type;
+{
+ aliasinfo ai;
+
+ (void) strcpy(ai.name, alias);
+ ai.type = type;
+
+ return(lfind((VOID *)&ai, (VOID *)aliases, &naliases,
+ sizeof(ai), aliascmp) != NULL);
+}
+
+
+/**********************************************************************
+ *
+ * more_aliases()
+ *
+ * This function allocates more space for the aliases list.
+ */
+
+static int more_aliases(nslots)
+ size_t nslots;
+{
+ aliasinfo *aip;
+
+ if (nslots == 0)
+ aip = (aliasinfo *) malloc(MOREALIASES * sizeof(*aip));
+ else
+ aip = (aliasinfo *) realloc(aliases,
+ (nslots + MOREALIASES) * sizeof(*aip));
+
+ if (aip != NULL) {
+ aliases = aip;
+ nslots += MOREALIASES;
+ }
+
+ return(aip != NULL);
+}
+
+
+/**********************************************************************
+ *
+ * dumpaliases()
+ *
+ * This function lists the contents of the aliases list.
+ */
+
+void dumpaliases()
+{
+ size_t n;
+
+ for (n = 0; n < naliases; n++) {
+ switch (aliases[n].type) {
+ case HOST:
+ (void) puts("HOST");
+ break;
+
+ case CMND:
+ (void) puts("CMND");
+ break;
+
+ case USER:
+ (void) puts("USER");
+ break;
+ }
+ (void) printf("\t%s\n", aliases[n].name);
+ }
+}
+
+
+/**********************************************************************
+ *
+ * list_matches()
+ *
+ * This function lists the contents of cm_list and ca_list for
+ * `sudo -l'.
+ */
+
+void list_matches()
+{
+ int i;
+ char *p;
+ struct command_alias *ca, key;
+
+ (void) puts("You may run the following commands on this host:");
+ for (i = 0; i < cm_list_len; i++) {
+
+ /* Print the runas list. */
+ (void) fputs(" ", stdout);
+ if (cm_list[i].runas) {
+ (void) putchar('(');
+ if ((p = strtok(cm_list[i].runas, ":")))
+ (void) fputs(p, stdout);
+ while ((p = strtok(NULL, ":"))) {
+ (void) fputs(", ", stdout);
+ (void) fputs(p, stdout);
+ }
+ (void) fputs(") ", stdout);
+ } else {
+ (void) fputs("(root) ", stdout);
+ }
+
+ /* Is a password required? */
+ if (cm_list[i].nopasswd == TRUE)
+ (void) fputs("NOPASSWD: ", stdout);
+
+ /* Print the actual command or expanded Cmnd_Alias. */
+ key.alias = cm_list[i].cmnd;
+ if ((ca = (struct command_alias *) lfind((VOID *) &key,
+ (VOID *) &ca_list[0], &ca_list_len, sizeof(key), cmndaliascmp)))
+ (void) puts(ca->entries);
+ else
+ (void) puts(cm_list[i].cmnd);
+ }
+
+ /* Be nice and free up space now that we are done. */
+ for (i = 0; i < ca_list_len; i++) {
+ (void) free(ca_list[i].alias);
+ (void) free(ca_list[i].entries);
+ }
+ (void) free(ca_list);
+ ca_list = NULL;
+
+ for (i = 0; i < cm_list_len; i++) {
+ (void) free(cm_list[i].runas);
+ (void) free(cm_list[i].cmnd);
+ }
+ (void) free(cm_list);
+ cm_list = NULL;
+}
+
+
+/**********************************************************************
+ *
+ * append()
+ *
+ * This function appends a source string to the destination prefixing
+ * a separator if one is given.
+ */
+
+static void append(src, dstp, dst_len, dst_size, separator)
+ char *src, **dstp;
+ size_t *dst_len, *dst_size;
+ int separator;
+{
+ /* Only add the separator if *dstp is non-NULL. */
+ size_t src_len = strlen(src) + ((separator && *dstp) ? 1 : 0);
+ char *dst = *dstp;
+
+ /* Assumes dst will be NULL if not set. */
+ if (dst == NULL) {
+ if ((dst = (char *) malloc(BUFSIZ)) == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ *dst_size = BUFSIZ;
+ *dst_len = 0;
+ *dstp = dst;
+ }
+
+ /* Allocate more space if necesary. */
+ if (*dst_size <= *dst_len + src_len) {
+ while (*dst_size <= *dst_len + src_len)
+ *dst_size += BUFSIZ;
+
+ if (!(dst = (char *) realloc(dst, *dst_size))) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ *dstp = dst;
+ }
+
+ /* Copy src -> dst adding a separator char if appropriate and adjust len. */
+ dst += *dst_len;
+ if (separator && *dst_len)
+ *dst++ = (char) separator;
+ (void) strcpy(dst, src);
+ *dst_len += src_len;
+}
+
+
+/**********************************************************************
+ *
+ * reset_aliases()
+ *
+ * This function frees up space used by the aliases list and resets
+ * the associated counters.
+ */
+
+void reset_aliases()
+{
+ if (aliases)
+ (void) free(aliases);
+ naliases = nslots = 0;
+}
+
+
+/**********************************************************************
+ *
+ * expand_ca_list()
+ *
+ * This function increments ca_list_len, allocating more space as necesary.
+ */
+
+static void expand_ca_list()
+{
+ if (++ca_list_len > ca_list_size) {
+ while ((ca_list_size += STACKINCREMENT) < ca_list_len);
+ if (ca_list == NULL) {
+ if ((ca_list = (struct command_alias *)
+ malloc(sizeof(struct command_alias) * ca_list_size)) == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ } else {
+ if ((ca_list = (struct command_alias *) realloc(ca_list,
+ sizeof(struct command_alias) * ca_list_size)) == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ }
+ }
+
+ ca_list[ca_list_len - 1].entries = NULL;
+}
+
+
+/**********************************************************************
+ *
+ * expand_match_list()
+ *
+ * This function increments cm_list_len, allocating more space as necesary.
+ */
+
+static void expand_match_list()
+{
+ if (++cm_list_len > cm_list_size) {
+ while ((cm_list_size += STACKINCREMENT) < cm_list_len);
+ if (cm_list == NULL) {
+ if ((cm_list = (struct command_match *)
+ malloc(sizeof(struct command_match) * cm_list_size)) == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ cm_list_len = 0;
+ } else {
+ if ((cm_list = (struct command_match *) realloc(cm_list,
+ sizeof(struct command_match) * cm_list_size)) == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ }
+ }
+
+ cm_list[cm_list_len].runas = cm_list[cm_list_len].cmnd = NULL;
+ cm_list[cm_list_len].nopasswd = FALSE;
+}
+
+
+/**********************************************************************
+ *
+ * init_parser()
+ *
+ * This function frees up spaced used by a previous parse 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) {
+ (void) free(match);
+ match = NULL;
+ top = 0;
+ parse_error = FALSE;
+ errorlineno = -1;
+ sudolineno = 1;
+ }
+
+ /* Allocate space for the matching stack. */
+ stacksize = STACKINCREMENT;
+ match = (struct matchstack *) malloc(sizeof(struct matchstack) * stacksize);
+ if (match == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ /* Allocate space for the match list (for `sudo -l'). */
+ if (printmatches == TRUE)
+ expand_match_list();
+}
diff --git a/gnu/usr.bin/sudo/sudo/pathnames.h b/gnu/usr.bin/sudo/sudo/pathnames.h
new file mode 100644
index 00000000000..0f4355ac896
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/pathnames.h
@@ -0,0 +1,90 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ * $Id: pathnames.h,v 1.1 1996/10/14 05:14:53 millert Exp $
+ */
+
+/*
+ * Pathnames to programs and files used by sudo.
+ */
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif /* HAVE_PATHS_H */
+
+#ifndef _PATH_DEV
+#define _PATH_DEV "/dev/"
+#endif /* _PATH_DEV */
+
+/*
+ * NOTE: _PATH_SUDO_SUDOERS is usually overriden by the Makefile
+ */
+#ifndef _PATH_SUDO_SUDOERS
+#define _PATH_SUDO_SUDOERS "/etc/sudoers"
+#endif /* _PATH_SUDO_SUDOERS */
+
+/*
+ * NOTE: _PATH_SUDO_STMP is usually overriden by the Makefile.
+ * _PATH_SUDO_STMP *MUST* be on the same partition
+ * as _PATH_SUDO_SUDOERS!
+ */
+#ifndef _PATH_SUDO_STMP
+#define _PATH_SUDO_STMP "/etc/stmp"
+#endif /* _PATH_SUDO_STMP */
+
+#ifndef _PATH_SUDO_TIMEDIR
+#define _PATH_SUDO_TIMEDIR _CONFIG_PATH_TIMEDIR
+#endif /* _PATH_SUDO_TIMEDIR */
+
+#ifndef _PATH_TTY
+#define _PATH_TTY "/dev/tty"
+#endif /* _PATH_TTY */
+
+/*
+ * The following paths are gleaned via configure but you can override
+ * configure's values here if you want.
+ */
+
+/*
+ * Where to put the sudo log file when logging to a file this
+ * is /var/log/sudo.log if /var/log exists, else /var/adm/sudo.log
+ */
+#ifndef _PATH_SUDO_LOGFILE
+#define _PATH_SUDO_LOGFILE _CONFIG_PATH_LOGFILE
+#endif /* _PATH_SUDO_LOGFILE */
+
+#ifndef _PATH_SENDMAIL
+#define _PATH_SENDMAIL _CONFIG_PATH_SENDMAIL
+#endif /* _PATH_SENDMAIL */
+
+#ifndef _PATH_VI
+#define _PATH_VI _CONFIG_PATH_VI
+#endif /* _PATH_VI */
+
+#ifndef _PATH_PWD
+#define _PATH_PWD _CONFIG_PATH_PWD
+#endif /* _PATH_PWD */
+
+#ifndef _PATH_MV
+#define _PATH_MV _CONFIG_PATH_MV
+#endif /* _PATH_MV */
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL _CONFIG_PATH_BSHELL
+#endif /* _PATH_BSHELL */
diff --git a/gnu/usr.bin/sudo/sudo/sudo.8 b/gnu/usr.bin/sudo/sudo/sudo.8
new file mode 100644
index 00000000000..77e6fdc4525
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/sudo.8
@@ -0,0 +1,378 @@
+.rn '' }`
+''' $RCSfile: sudo.8,v $$Revision: 1.1 $$Date: 1996/10/14 05:14:53 $
+'''
+''' $Log: sudo.8,v $
+''' Revision 1.1 1996/10/14 05:14:53 millert
+''' sudo 1.5.2
+'''
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.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 L' '
+.ds R' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds L' `
+.ds R' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH sudo 8 "1.5.2" "6/Oct/96" "MAINTENANCE COMMANDS"
+.IX Title "sudo 8"
+.UC
+.IX Name "sudo - execute a command as the superuser"
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" 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 ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.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 ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" 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 v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.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
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'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 v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. 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
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+.IX Header "NAME"
+sudo \- execute a command as the superuser
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+\fBsudo\fR \fB\-V\fR | \fB\-h\fR | \fB\-l\fR | \fB\-v\fR | \fB\-k\fR | \fB\-s\fR | \fB\-H\fR |
+[ \fB\-b\fR ] | [ \fB\-p\fR prompt ] [ \fB\-u\fR username/#uid] \fIcommand\fR
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\fBsudo\fR allows a permitted user to execute a \fIcommand\fR
+as the superuser (real and effective uid and gid are set
+to \f(CW0\fR and root's group as set in the passwd file respectively).
+.PP
+\fBsudo\fR determines who is an authorized user by consulting the
+file \fI/etc/sudoers\fR. By giving \fBsudo\fR the \f(CW-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 password is
+not entered with N minutes (again, this is defined at installation
+time and defaults to 5 minutes).
+.PP
+If an unauthorized user executes \fBsudo\fR, mail will be sent from the
+user to the local authorities (defined at installation time).
+.PP
+\fBsudo\fR was designed to log via the 4.3 BSD \fIsyslog\fR\|(3) facility but
+can log to a file instead if so desired (or to both syslog and a file).
+.PP
+All preferences are defined at installation time and are derived from
+the options.h and pathnames.h include files as well as as well as the
+Makefile.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+\fBsudo\fR accepts the following command line options:
+.Ip "-V" 4
+.IX Item "-V"
+The \f(CW-V\fR (\fIversion\fR) option causes \fBsudo\fR to print the
+version number and exit.
+.Ip "-l" 4
+.IX Item "-l"
+The \f(CW-l\fR (\fIlist\fR) option will list out the allowed and
+forbidden commands for the user on the current host.
+.Ip "-h" 4
+.IX Item "-h"
+The \f(CW-h\fR (\fIhelp\fR) option causes \fBsudo\fR to print the version
+of \fBsudo\fR and a usage message before exiting.
+.Ip "-v" 4
+.IX Item "-v"
+If given the \f(CW-v\fR (\fIvalidate\fR) option, \fBsudo\fR will update the
+user's timestamp file, prompting for a password if necessary.
+This extends the \fBsudo\fR timeout to for another N minutes
+(where N is defined at installation time and defaults to 5
+minutes) but does not run a command.
+.Ip "-k" 4
+.IX Item "-k"
+The \f(CW-k\fR (\fIkill\fR) option to \fBsudo\fR removes the user's timestamp
+file, thus requiring a password the next time \fBsudo\fR is run.
+This option does not require a password and was added to
+allow a user to revoke \fBsudo\fR permissions from a .logout file.
+.Ip "-b" 4
+.IX Item "-b"
+The \f(CW-b\fR (\fIbackground\fR) option tells \fBsudo\fR to run the given
+command in the background. Note that if you use the \f(CW-b\fR
+option you cannot use shell job control to manipulate the command.
+.Ip "-p" 4
+.IX Item "-p"
+The \f(CW-p\fR (\fIprompt\fR) option allows you to override the default
+password prompt and use a custom one. If the password prompt
+contains the \f(CW%u\fR escape, \f(CW%u\fR will be replaced by the user's
+login name. Similarly, \f(CW%h\fR will be replaced by the local
+hostname.
+.Ip "-u" 4
+.IX Item "-u"
+The \f(CW-u\fR (\fIuser\fR) option causes sudo to run the specified command
+as a user other than \fIroot\fR. To specify a \fIuid\fR instead of a
+\fIusername\fR, use \*(L"#uid\*(R".
+.Ip "-s" 4
+.IX Item "-s"
+The \f(CW-s\fR (\fIshell\fR) option runs the shell specified by the \fI\s-1SHELL\s0\fR
+environmental variable if it is set or the shell as specified
+in \fIpasswd\fR\|(5).
+.Ip "-H" 4
+.IX Item "-H"
+The \f(CW-H\fR (\fI\s-1HOME\s0\fR) option sets the \fI\s-1HOME\s0\fR environmental variable
+to the homedir of the target user (root by default) as specified
+in \fIpasswd\fR\|(5).
+.Ip "--" 4
+.IX Item "--"
+The \f(CW--\fR flag indicates that \fBsudo\fR should stop processing command
+line arguments. It is most useful in conjunction with the \f(CW-s\fR flag.
+.SH "RETURN VALUES"
+.IX Header "RETURN VALUES"
+\fBsudo\fR quits with an exit value of 1 if there is a
+configuration/permission problem or if \fBsudo\fR cannot execute
+the given command. In the latter case the error string is
+printed to stderr via \fIperror\fR\|(3). If \fBsudo\fR cannot \fIstat\fR\|(2)
+one or more entries in the user's PATH the error is printed
+on stderr via \fIperror\fR\|(3). (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 \fIstat\fR\|(3) to return
+\*(L"permission denied\*(R" is if you are running an automounter and
+one of the directories in your PATH is on a machine that is
+currently unreachable.
+.SH "SECURITY NOTES"
+.IX Header "SECURITY NOTES"
+\fBsudo\fR tries to be safe when executing external commands.
+Variables that control how dynamic loading and binding is
+done can be used to subvert the program that \fBsudo\fR runs.
+To combat this the \f(CWLD_*\fR, \f(CWSHLIB_PATH\fR (HP\-UX only),
+\f(CWLIBPATH\fR (AIX only), and \f(CW_RLD_*\fR environmental variables are
+removed from the environment passed on to all commands executed.
+\fBsudo\fR will also remove the \f(CWIFS\fR, \f(CWENV\fR, \f(CWBASH_ENV\fR
+and \f(CWKRB_CONF\fR variables as they too can pose a threat.
+.PP
+To prevent command spoofing, \fBsudo\fR checks "." and "" (both
+denoting current directory) last when searching for a command
+in the user's PATH (if one or both are in the PATH).
+Note, however, that the actual PATH environmental variable
+is \fInot\fR modified and is passed unchanged to the program that
+\fBsudo\fR executes.
+.PP
+For security reasons, if your OS supports shared libraries,
+\fBsudo\fR should always be statically linked unless the
+dynamic loader disables user-defined library search paths
+for setuid programs. (Most modern dynamic loaders do this.)
+.PP
+\fBsudo\fR will check the ownership of its timestamp directory
+(\fI/var/run/sudo\fR or \fI/tmp/.odus\fR by default) and ignore
+the directory's contents if it is not owned by root and
+only read, writable, and executable by root. On systems
+that allow users to give files away to root (via chown),
+if the timestamp directory is located in a directory writable
+by anyone (ie: \fI/tmp\fR), it is possible for a user to create
+the timestamp directory before \fBsudo\fR is run.
+However, because \fBsudo\fR checks the ownership and mode of
+the directory, the only damage that can be done is to \*(L"hide\*(R"
+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 (\fI/var/adm/sudo\fR for instance).
+.PP
+\f(CWsudo\fR will not honor timestamp files set far in the
+future. Timestamp files with a date greater than
+current_time + 2 * \f(CWTIMEOUT\fR will be ignored and
+sudo will log the anomaly. This is done to keep a user
+from creating his/her own timestamp file with a bogus
+date.
+.SH "FILES"
+.IX Header "FILES"
+.PP
+.Vb 1
+\& /etc/sudoers file of authorized users.
+.Ve
+.SH "ENVIRONMENT VARIABLES"
+.IX Header "ENVIRONMENT VARIABLES"
+.PP
+.Vb 10
+\& PATH Set to a sane value if SECURE_PATH is set
+\& SHELL Used to determine shell to run with -s option
+\& HOME In -s mode, set to homedir of root (or runas user)
+\& if built with the SHELL_SETS_HOME option
+\& SUDO_PROMPT Replaces the default password prompt
+\& 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
+\& SUDO_GID Set to the gid of the user who invoked sudo
+\& SUDO_PS1 If set, PS1 will be set to its value
+.Ve
+.SH "AUTHORS"
+.IX Header "AUTHORS"
+Many people have worked on \fBsudo\fR over the years, this
+version consists of code written primarily by:
+.PP
+.Vb 4
+\& Jeff Nieusma <nieusma@FirstLink.com>
+\& David Hieb <davehieb@internetone.com>
+\& Todd Miller <Todd.Miller@courtesan.com>
+\& Chris Jepeway <jepeway@cs.utk.edu>
+.Ve
+See the HISTORY file in the \fBsudo\fR distribution for more details.
+.PP
+Please send all bugs, comments, and changes to sudo-bugs@courtesan.com.
+.SH "DISCLAIMER"
+.IX Header "DISCLAIMER"
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+.PP
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+675 Mass Ave, Cambridge, MA 02139, USA.
+.SH "CAVEATS"
+.IX Header "CAVEATS"
+There is no easy way to prevent a user from gaining a root shell if
+that user has access to commands allow shell escapes.
+Running shell scripts via \fBsudo\fR can expose the same kernel bugs
+that make setuid shell scripts unsafe on some operating systems.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\fIsudoers\fR\|(5), \fIvisudo\fR\|(8), \fIsu\fR\|(1).
+
+.rn }` ''
diff --git a/gnu/usr.bin/sudo/sudo/sudo.c b/gnu/usr.bin/sudo/sudo/sudo.c
new file mode 100644
index 00000000000..7e17f18c944
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/sudo.c
@@ -0,0 +1,999 @@
+/*
+ * CU sudo version 1.5.2 (based on Root Group sudo version 1.1)
+ *
+ * This software comes with no waranty whatsoever, use at your own risk.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ */
+
+/*
+ * sudo version 1.1 allows users to execute commands as root
+ * Copyright (C) 1991 The Root Group, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ **************************************************************************
+ *
+ * sudo.c
+ *
+ * This is the main() routine for sudo
+ *
+ * sudo is a program to allow users to execute commands
+ * as root. The commands are defined in a global network-
+ * wide file and can be distributed.
+ *
+ * sudo has been hacked far and wide. Too many people to
+ * know about. It's about time to come up with a secure
+ * version that will work well in a network.
+ *
+ * This most recent version is done by:
+ *
+ * Jeff Nieusma <nieusma@rootgroup.com>
+ * Dave Hieb <davehieb@rootgroup.com>
+ *
+ * However, due to the fact that both of the above are no longer
+ * working at Root Group, I am maintaining the "CU version" of
+ * sudo.
+ * Todd Miller <Todd.Miller@courtesan.com>
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: sudo.c,v 1.1 1996/10/14 05:14:54 millert Exp $";
+#endif /* lint */
+
+#define MAIN
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+#include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#include <pwd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#if (SHADOW_TYPE == SPW_SECUREWARE)
+# ifdef __hpux
+# include <hpsecurity.h>
+# else
+# include <sys/security.h>
+# endif /* __hpux */
+# include <prot.h>
+#endif /* SPW_SECUREWARE */
+#ifdef HAVE_DCE
+#include <pthread.h>
+#endif /* HAVE_DCE */
+
+#include "sudo.h"
+#include <options.h>
+#include "version.h"
+
+#ifndef STDC_HEADERS
+#ifndef __GNUC__ /* gcc has its own malloc */
+extern char *malloc __P((size_t));
+#endif /* __GNUC__ */
+#ifdef HAVE_STRDUP
+extern char *strdup __P((const char *));
+#endif /* HAVE_STRDUP */
+extern char *getenv __P((char *));
+#endif /* STDC_HEADERS */
+
+
+/*
+ * Local type declarations
+ */
+struct env_table {
+ char *name;
+ int len;
+};
+
+
+/*
+ * Prototypes
+ */
+static int parse_args __P((void));
+static void usage __P((int));
+static void load_globals __P((int));
+static int check_sudoers __P((void));
+static void load_cmnd __P((int));
+static void add_env __P((int));
+static void clean_env __P((char **, struct env_table *));
+extern int user_is_exempt __P((void));
+extern struct passwd *sudo_getpwuid __P((uid_t));
+extern void list_matches __P((void));
+
+/*
+ * Globals
+ */
+int Argc;
+char **Argv;
+int NewArgc = 0;
+char **NewArgv = NULL;
+struct passwd *user_pw_ent;
+char *runas_user = "root";
+char *cmnd = NULL;
+char *cmnd_args = NULL;
+char *tty = NULL;
+char *prompt;
+char host[MAXHOSTNAMELEN + 1];
+char *shost;
+char cwd[MAXPATHLEN + 1];
+struct stat cmnd_st;
+static char *runas_homedir = NULL;
+extern struct interface *interfaces;
+extern int num_interfaces;
+extern int printmatches;
+
+/*
+ * Table of "bad" envariables to remove and len for strncmp()
+ */
+struct env_table badenv_table[] = {
+ { "IFS=", 4 },
+ { "LD_", 3 },
+ { "_RLD_", 5 },
+#ifdef __hpux
+ { "SHLIB_PATH=", 11 },
+#endif /* __hpux */
+#ifdef _AIX
+ { "LIBPATH=", 8 },
+#endif /* _AIX */
+#ifdef HAVE_KERB4
+ { "KRB_CONF", 8 },
+#endif
+ { "ENV=", 4 },
+ { "BASH_ENV=", 9 },
+ { (char *) NULL, 0 }
+};
+
+
+/********************************************************************
+ *
+ * main()
+ *
+ * the driving force behind sudo...
+ */
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int rtn;
+ int sudo_mode = MODE_RUN;
+ extern char ** environ;
+
+#if (SHADOW_TYPE == SPW_SECUREWARE)
+ (void) set_auth_parameters(argc, argv);
+#endif /* SPW_SECUREWARE */
+
+ Argv = argv;
+ Argc = argc;
+
+ if (geteuid() != 0) {
+ (void) fprintf(stderr, "Sorry, %s must be setuid root.\n", Argv[0]);
+ exit(1);
+ }
+
+ /*
+ * set the prompt based on $SUDO_PROMPT (can be overridden by `-p')
+ */
+ if ((prompt = getenv("SUDO_PROMPT")) == NULL)
+ prompt = PASSPROMPT;
+
+ /*
+ * parse our arguments
+ */
+ sudo_mode = parse_args();
+
+ switch (sudo_mode) {
+ case MODE_VERSION:
+ case MODE_HELP:
+ (void) printf("CU Sudo version %s\n", version);
+ if (sudo_mode == MODE_VERSION)
+ exit(0);
+ else
+ usage(0);
+ break;
+ case MODE_VALIDATE:
+ cmnd = "validate";
+ break;
+ case MODE_KILL:
+ cmnd = "kill";
+ break;
+ case MODE_LIST:
+ cmnd = "list";
+ printmatches = 1;
+ break;
+ }
+
+ /* must have a command to run unless got -s */
+ if (cmnd == NULL && NewArgc == 0 && !(sudo_mode & MODE_SHELL))
+ usage(1);
+
+ /*
+ * Close all file descriptors to make sure we have a nice
+ * clean slate from which to work.
+ */
+#ifdef HAVE_SYSCONF
+ for (rtn = sysconf(_SC_OPEN_MAX) - 1; rtn > 3; rtn--)
+ (void) close(rtn);
+#else
+ for (rtn = getdtablesize() - 1; rtn > 3; rtn--)
+ (void) close(rtn);
+#endif /* HAVE_SYSCONF */
+
+ clean_env(environ, badenv_table);
+
+ load_globals(sudo_mode); /* load global variables used throughout sudo */
+
+ /*
+ * If we got the '-s' option (run shell) we need to redo NewArgv
+ * and NewArgc. This can only be done after load_globals().
+ */
+ if ((sudo_mode & MODE_SHELL)) {
+ char **dst, **src = NewArgv;
+
+ NewArgv = (char **) malloc (sizeof(char *) * (++NewArgc + 1));
+ if (NewArgv == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ /* add the shell as argv[0] */
+ if (user_shell && *user_shell) {
+ if ((NewArgv[0] = strrchr(user_shell, '/') + 1) == (char *) 1)
+ NewArgv[0] = user_shell;
+ } else {
+ (void) fprintf(stderr, "%s: Unable to determine shell.", Argv[0]);
+ exit(1);
+ }
+
+ /* copy the args from Argv */
+ for (dst = NewArgv + 1; (*dst = *src) != NULL; ++src, ++dst)
+ ;
+ }
+
+ rtn = check_sudoers(); /* check mode/owner on _PATH_SUDO_SUDOERS */
+ if (rtn != ALL_SYSTEMS_GO) {
+ log_error(rtn);
+ set_perms(PERM_FULL_USER, sudo_mode);
+ inform_user(rtn);
+ exit(1);
+ }
+
+#ifdef SECURE_PATH
+ /* replace the PATH envariable with a secure one */
+ if (!user_is_exempt() && sudo_setenv("PATH", SECURE_PATH)) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+#endif /* SECURE_PATH */
+
+ if ((sudo_mode & MODE_RUN)) {
+ load_cmnd(sudo_mode); /* load the cmnd global variable */
+ } else if (sudo_mode == MODE_KILL) {
+ remove_timestamp(); /* remove the timestamp ticket file */
+ exit(0);
+ }
+
+ add_env(!(sudo_mode & MODE_SHELL)); /* add in SUDO_* envariables */
+
+ /* validate the user but don't search for "validate" */
+ rtn = validate((sudo_mode != MODE_VALIDATE && sudo_mode != MODE_LIST));
+
+ switch (rtn) {
+
+ case VALIDATE_OK:
+ case VALIDATE_OK_NOPASS:
+ if (rtn != VALIDATE_OK_NOPASS)
+ check_user();
+ log_error(ALL_SYSTEMS_GO);
+ if (sudo_mode == MODE_VALIDATE)
+ exit(0);
+ else if (sudo_mode == MODE_LIST) {
+ list_matches();
+ exit(0);
+ }
+
+ /* become specified user or root */
+ set_perms(PERM_RUNAS, sudo_mode);
+
+ /* set $HOME for `sudo -H' */
+ if ((sudo_mode & MODE_RESET_HOME) && runas_homedir)
+ (void) sudo_setenv("HOME", runas_homedir);
+
+#ifndef PROFILING
+ if ((sudo_mode & MODE_BACKGROUND) && fork() > 0) {
+ exit(0);
+ } else {
+ /*
+ * Make sure we are not being spoofed. The stat should
+ * be cheap enough to make this almost bulletproof.
+ */
+ if (cmnd_st.st_dev) {
+ struct stat st;
+
+ if (stat(cmnd, &st) < 0) {
+ (void) fprintf(stderr, "%s: unable to stat %s: ",
+ Argv[0], cmnd);
+ perror("");
+ exit(1);
+ }
+
+ if (st.st_dev != cmnd_st.st_dev ||
+ st.st_ino != cmnd_st.st_ino) {
+ /* log and send mail, then bitch */
+ log_error(SPOOF_ATTEMPT);
+ inform_user(SPOOF_ATTEMPT);
+ exit(1);
+ }
+ }
+ EXEC(cmnd, NewArgv); /* run the command */
+ }
+#else
+ exit(0);
+#endif /* PROFILING */
+ /*
+ * If we got here then the exec() failed...
+ */
+ (void) fprintf(stderr, "%s: ", Argv[0]);
+ perror(cmnd);
+ exit(-1);
+ break;
+
+ default:
+ log_error(rtn);
+ set_perms(PERM_FULL_USER, sudo_mode);
+ inform_user(rtn);
+ exit(1);
+ break;
+ }
+}
+
+
+
+/**********************************************************************
+ *
+ * load_globals()
+ *
+ * This function primes these important global variables:
+ * user_pw_ent, host, cwd, interfaces.
+ */
+
+static void load_globals(sudo_mode)
+ int sudo_mode;
+{
+ char *p;
+#ifdef FQDN
+ struct hostent *h_ent;
+#endif /* FQDN */
+
+ /*
+ * Get a local copy of the user's struct passwd with the shadow password
+ * if necesary. It is assumed that euid is 0 at this point so we
+ * can read the shadow passwd file if necesary.
+ */
+ user_pw_ent = sudo_getpwuid(getuid());
+ set_perms(PERM_ROOT, sudo_mode);
+ set_perms(PERM_USER, sudo_mode);
+ if (user_pw_ent == NULL) {
+ /* need to make a fake user_pw_ent */
+ struct passwd pw_ent;
+ char pw_name[MAX_UID_T_LEN+1];
+
+ /* fill in uid and name fields with the uid */
+ pw_ent.pw_uid = getuid();
+ (void) sprintf(pw_name, "%ld", (long) pw_ent.pw_uid);
+ pw_ent.pw_name = pw_name;
+ user_pw_ent = &pw_ent;
+
+ /* complain, log, and die */
+ log_error(GLOBAL_NO_PW_ENT);
+ inform_user(GLOBAL_NO_PW_ENT);
+ exit(1);
+ }
+
+#ifdef HAVE_TZSET
+ (void) tzset(); /* set the timezone if applicable */
+#endif /* HAVE_TZSET */
+
+ /*
+ * Need to get tty early since it's used for logging
+ */
+ if ((tty = (char *) ttyname(0)) || (tty = (char *) ttyname(1))) {
+ if (strncmp(tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
+ tty += sizeof(_PATH_DEV) - 1;
+ if ((tty = (char *) strdup(tty)) == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ } else
+ tty = "none";
+
+#ifdef UMASK
+ (void) umask((mode_t)UMASK);
+#endif /* UMASK */
+
+#ifdef NO_ROOT_SUDO
+ if (user_uid == 0) {
+ (void) fprintf(stderr,
+ "You are already root, you don't need to use sudo.\n");
+ exit(1);
+ }
+#endif
+
+ /*
+ * so we know where we are... (do as user)
+ */
+ if (!getwd(cwd)) {
+ /* try as root... */
+ set_perms(PERM_ROOT, sudo_mode);
+ if (!getwd(cwd)) {
+ (void) fprintf(stderr, "%s: Can't get working directory!\n",
+ Argv[0]);
+ (void) strcpy(cwd, "unknown");
+ }
+ set_perms(PERM_USER, sudo_mode);
+ }
+
+ /*
+ * load the host global variable from gethostname() and use
+ * gethostbyname() if we want to be sure it is fully qualified.
+ */
+ if ((gethostname(host, MAXHOSTNAMELEN))) {
+ strcpy(host, "localhost");
+ log_error(GLOBAL_NO_HOSTNAME);
+ inform_user(GLOBAL_NO_HOSTNAME);
+ exit(2);
+ }
+#ifdef FQDN
+ if ((h_ent = gethostbyname(host)) == NULL)
+ log_error(GLOBAL_HOST_UNREGISTERED);
+ else
+ strcpy(host, h_ent -> h_name);
+#endif /* FQDN */
+
+ /*
+ * "host" is the (possibly fully-qualified) hostname and
+ * "shost" is the unqualified form of the hostname.
+ */
+ if ((p = strchr(host, '.'))) {
+ *p = '\0';
+ if ((shost = strdup(host)) == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ *p = '.';
+ } else {
+ shost = &host[0];
+ }
+
+ /*
+ * load a list of ip addresses and netmasks into
+ * the interfaces array.
+ */
+ load_interfaces();
+}
+
+
+
+/**********************************************************************
+ *
+ * parse_args()
+ *
+ * this function parses the arguments to sudo
+ */
+
+static int parse_args()
+{
+ int ret = MODE_RUN; /* what mode is suod to be run in? */
+ int excl = 0; /* exclusive arg, no others allowed */
+
+ NewArgv = Argv + 1;
+ NewArgc = Argc - 1;
+
+#ifdef SHELL_IF_NO_ARGS
+ if (Argc < 2) { /* no options and no command */
+ ret |= MODE_SHELL;
+ return(ret);
+ }
+#else
+ if (Argc < 2) /* no options and no command */
+ usage(1);
+#endif /* SHELL_IF_NO_ARGS */
+
+ while (NewArgc > 0 && NewArgv[0][0] == '-') {
+ if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0') {
+ (void) fprintf(stderr, "%s: Please use single character options\n",
+ Argv[0]);
+ usage(1);
+ }
+
+ if (excl)
+ usage(1); /* only one -? option allowed */
+
+ switch (NewArgv[0][1]) {
+ case 'p':
+ /* must have an associated prompt */
+ if (NewArgv[1] == NULL)
+ usage(1);
+
+ prompt = NewArgv[1];
+
+ /* shift Argv over and adjust Argc */
+ NewArgc--;
+ NewArgv++;
+ break;
+ case 'u':
+ /* must have an associated runas user */
+ if (NewArgv[1] == NULL)
+ usage(1);
+
+ runas_user = NewArgv[1];
+
+ /* shift Argv over and adjust Argc */
+ NewArgc--;
+ NewArgv++;
+ break;
+ case 'b':
+ ret |= MODE_BACKGROUND;
+ break;
+ case 'v':
+ ret = MODE_VALIDATE;
+ excl++;
+ break;
+ case 'k':
+ ret = MODE_KILL;
+ excl++;
+ break;
+ case 'l':
+ ret = MODE_LIST;
+ excl++;
+ break;
+ case 'V':
+ ret = MODE_VERSION;
+ excl++;
+ break;
+ case 'h':
+ ret = MODE_HELP;
+ excl++;
+ break;
+ case 's':
+ ret |= MODE_SHELL;
+#ifdef SHELL_SETS_HOME
+ ret |= MODE_RESET_HOME;
+#endif /* SHELL_SETS_HOME */
+ break;
+ case 'H':
+ ret |= MODE_RESET_HOME;
+ break;
+ case '-':
+ NewArgc--;
+ NewArgv++;
+#ifdef SHELL_IF_NO_ARGS
+ if (ret == MODE_RUN)
+ ret |= MODE_SHELL;
+#endif /* SHELL_IF_NO_ARGS */
+ return(ret);
+ case '\0':
+ (void) fprintf(stderr, "%s: '-' requires an argument\n",
+ Argv[0]);
+ usage(1);
+ default:
+ (void) fprintf(stderr, "%s: Illegal option %s\n", Argv[0],
+ NewArgv[0]);
+ usage(1);
+ }
+ NewArgc--;
+ NewArgv++;
+ }
+
+ if (NewArgc > 0 && (ret == MODE_VALIDATE || ret == MODE_KILL ||
+ ret == MODE_LIST))
+ usage(1);
+
+ return(ret);
+}
+
+
+
+/**********************************************************************
+ *
+ * usage()
+ *
+ * this function just gives you instructions and exits
+ */
+
+static void usage(exit_val)
+ int exit_val;
+{
+ (void) fprintf(stderr, "usage: %s -V | -h | -l | -v | -k | -H | [-b] [-p prompt] [-u username/#uid] -s | <command>\n", Argv[0]);
+ exit(exit_val);
+}
+
+
+
+/**********************************************************************
+ *
+ * add_env()
+ *
+ * this function adds sudo-specific variables into the environment
+ */
+
+static void add_env(contiguous)
+ int contiguous;
+{
+ char idstr[MAX_UID_T_LEN + 1];
+ size_t size;
+ char *buf;
+
+ /* add the SUDO_COMMAND envariable (cmnd + args) */
+ size = strlen(cmnd) + 1;
+ if (NewArgc > 1) {
+ char *to, **from;
+
+ if (contiguous) {
+ size += (size_t) NewArgv[NewArgc-1] + strlen(NewArgv[NewArgc-1]) -
+ (size_t) NewArgv[1] + 1;
+ } else {
+ for (from = &NewArgv[1]; *from; from++)
+ size += strlen(*from) + 1;
+ }
+
+ if ((buf = (char *) malloc(size)) == NULL) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ /*
+ * Copy the command and it's arguments info buf
+ */
+ (void) strcpy(buf, cmnd);
+ to = buf + strlen(cmnd);
+ for (from = &NewArgv[1]; *from; from++) {
+ *to++ = ' ';
+ (void) strcpy(to, *from);
+ to += strlen(*from);
+ }
+ } else {
+ buf = cmnd;
+ }
+ if (sudo_setenv("SUDO_COMMAND", buf)) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+ if (NewArgc > 1)
+ (void) free(buf);
+
+ /* grab a pointer to the flat arg string from the environment */
+ if (NewArgc > 1 && (cmnd_args = getenv("SUDO_COMMAND"))) {
+ if ((cmnd_args = strchr(cmnd_args, ' ')))
+ cmnd_args++;
+ else
+ cmnd_args = NULL;
+ }
+
+ /* add the SUDO_USER envariable */
+ if (sudo_setenv("SUDO_USER", user_name)) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ /* add the SUDO_UID envariable */
+ (void) sprintf(idstr, "%ld", (long) user_uid);
+ if (sudo_setenv("SUDO_UID", idstr)) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ /* add the SUDO_GID envariable */
+ (void) sprintf(idstr, "%ld", (long) user_gid);
+ if (sudo_setenv("SUDO_GID", idstr)) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+
+ /* set PS1 if SUDO_PS1 is set */
+ if ((buf = getenv("SUDO_PS1")))
+ if (sudo_setenv("PS1", buf)) {
+ perror("malloc");
+ (void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
+ exit(1);
+ }
+}
+
+
+
+/**********************************************************************
+ *
+ * load_cmnd()
+ *
+ * This function sets the cmnd global variable
+ */
+
+static void load_cmnd(sudo_mode)
+ int sudo_mode;
+{
+ if (strlen(NewArgv[0]) > MAXPATHLEN) {
+ errno = ENAMETOOLONG;
+ (void) fprintf(stderr, "%s: %s: Pathname too long\n", Argv[0],
+ NewArgv[0]);
+ exit(1);
+ }
+
+ /*
+ * Resolve the path
+ */
+ if ((cmnd = find_path(NewArgv[0])) == NULL) {
+ (void) fprintf(stderr, "%s: %s: command not found\n", Argv[0],
+ NewArgv[0]);
+ exit(1);
+ }
+}
+
+
+
+/**********************************************************************
+ *
+ * check_sudoers()
+ *
+ * This function check to see that the sudoers file is owned by
+ * uid SUDOERS_UID, gid SUDOERS_GID and is mode SUDOERS_MODE.
+ */
+
+static int check_sudoers()
+{
+ struct stat statbuf;
+ int fd = -1;
+ char c;
+ int rtn = ALL_SYSTEMS_GO;
+
+ /*
+ * Fix the mode and group on sudoers file from old default.
+ * Only works if filesystem is readable/writable by root.
+ */
+ set_perms(PERM_ROOT, 0);
+ if (!lstat(_PATH_SUDO_SUDOERS, &statbuf) && SUDOERS_UID == statbuf.st_uid) {
+ if (SUDOERS_MODE != 0400 && (statbuf.st_mode & 0007777) == 0400) {
+ if (chmod(_PATH_SUDO_SUDOERS, SUDOERS_MODE) == 0) {
+ (void) fprintf(stderr, "%s: fixed mode on %s\n",
+ Argv[0], _PATH_SUDO_SUDOERS);
+ if (statbuf.st_gid != SUDOERS_GID) {
+ if (!chown(_PATH_SUDO_SUDOERS,GID_NO_CHANGE,SUDOERS_GID)) {
+ (void) fprintf(stderr, "%s: set group on %s\n",
+ Argv[0], _PATH_SUDO_SUDOERS);
+ statbuf.st_gid = SUDOERS_GID;
+ } else {
+ (void) fprintf(stderr,"%s: Unable to set group on %s: ",
+ Argv[0], _PATH_SUDO_SUDOERS);
+ perror("");
+ }
+ }
+ } else {
+ (void) fprintf(stderr, "%s: Unable to fix mode on %s: ",
+ Argv[0], _PATH_SUDO_SUDOERS);
+ perror("");
+ }
+ }
+ }
+
+ set_perms(PERM_SUDOERS, 0);
+
+ if ((fd = open(_PATH_SUDO_SUDOERS, O_RDONLY)) < 0 || read(fd, &c, 1) == -1)
+ rtn = NO_SUDOERS_FILE;
+ else if (lstat(_PATH_SUDO_SUDOERS, &statbuf))
+ rtn = NO_SUDOERS_FILE;
+ else if (!S_ISREG(statbuf.st_mode))
+ rtn = SUDOERS_NOT_FILE;
+ else if ((statbuf.st_mode & 0007777) != SUDOERS_MODE)
+ rtn = SUDOERS_WRONG_MODE;
+ else if (statbuf.st_uid != SUDOERS_UID || statbuf.st_gid != SUDOERS_GID)
+ rtn = SUDOERS_WRONG_OWNER;
+
+ if (fd != -1)
+ (void) close(fd);
+
+ set_perms(PERM_ROOT, 0);
+ set_perms(PERM_USER, 0);
+
+ return(rtn);
+}
+
+
+
+/**********************************************************************
+ *
+ * set_perms()
+ *
+ * this function sets real and effective uids and gids based on perm.
+ */
+
+void set_perms(perm, sudo_mode)
+ int perm;
+ int sudo_mode;
+{
+ struct passwd *pw_ent;
+
+ switch (perm) {
+ case PERM_ROOT:
+ if (setuid(0)) {
+ perror("setuid(0)");
+ exit(1);
+ }
+ break;
+
+ case PERM_USER:
+ (void) setgid(user_gid);
+
+ if (seteuid(user_uid)) {
+ perror("seteuid(user_uid)");
+ exit(1);
+ }
+ break;
+
+ case PERM_FULL_USER:
+ if (setuid(0)) {
+ perror("setuid(0)");
+ exit(1);
+ }
+
+ (void) setgid(user_gid);
+
+ if (setuid(user_uid)) {
+ perror("setuid(user_uid)");
+ exit(1);
+ }
+
+ break;
+ case PERM_RUNAS:
+ if (setuid(0)) {
+ perror("setuid(0)");
+ exit(1);
+ }
+
+ /* XXX - add group/gid support */
+ if (*runas_user == '#') {
+ if (setuid(atoi(runas_user + 1))) {
+ (void) fprintf(stderr,
+ "%s: cannot set uid to %s: ",
+ Argv[0], runas_user);
+ perror("");
+ exit(1);
+ }
+ } else {
+ if (!(pw_ent = getpwnam(runas_user))) {
+ (void) fprintf(stderr,
+ "%s: no passwd entry for %s!\n",
+ Argv[0], runas_user);
+ exit(1);
+ }
+
+ if (setgid(pw_ent->pw_gid)) {
+ (void) fprintf(stderr,
+ "%s: cannot set gid to %d: ",
+ Argv[0], pw_ent->pw_gid);
+ perror("");
+ exit(1);
+ }
+
+ if (setuid(pw_ent->pw_uid)) {
+ (void) fprintf(stderr,
+ "%s: cannot set uid to %d: ",
+ Argv[0], pw_ent->pw_uid);
+ perror("");
+ exit(1);
+ }
+ if (sudo_mode & MODE_RESET_HOME)
+ runas_homedir = pw_ent->pw_dir;
+ }
+
+ break;
+ case PERM_SUDOERS:
+ if (setuid(0)) {
+ perror("setuid(0)");
+ exit(1);
+ }
+
+ if (setgid(SUDOERS_GID)) {
+ perror("setgid(SUDOERS_GID)");
+ exit(1);
+ }
+
+ /*
+ * If SUDOERS_UID == 0 we need to use
+ * a different uid in order to avoid
+ * NFS lossage. Using uid 1 is a bit
+ * bogus but should be safe.
+ */
+ if (SUDOERS_UID == 0) {
+ if (seteuid(1)) {
+ perror("seteuid(1)");
+ exit(1);
+ }
+ } else {
+ if (seteuid(SUDOERS_UID)) {
+ perror("seteuid(SUDOERS_UID)");
+ exit(1);
+ }
+ }
+
+ break;
+ }
+}
+
+
+
+/**********************************************************************
+ *
+ * clean_env()
+ *
+ * This function removes things from the environment that match the
+ * entries in badenv_table. It would be nice to add in the SUDO_*
+ * variables here as well but cmnd has not been defined at this point.
+ */
+
+static void clean_env(envp, badenv_table)
+ char **envp;
+ struct env_table *badenv_table;
+{
+ struct env_table *bad;
+ char **cur;
+
+ /*
+ * Remove any envars that match entries in badenv_table
+ */
+ for (cur = envp; *cur; cur++) {
+ for (bad = badenv_table; bad -> name; bad++) {
+ if (strncmp(*cur, bad -> name, bad -> len) == 0) {
+ /* got a match so remove it */
+ char **move;
+
+ for (move = cur; *move; move++)
+ *move = *(move + 1);
+
+ cur--;
+
+ break;
+ }
+ }
+ }
+}
diff --git a/gnu/usr.bin/sudo/sudo/sudo.h b/gnu/usr.bin/sudo/sudo/sudo.h
new file mode 100644
index 00000000000..99e1f755255
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/sudo.h
@@ -0,0 +1,236 @@
+/*
+ * CU sudo version 1.5.2 (based on Root Group sudo version 1.1)
+ *
+ * This software comes with no waranty whatsoever, use at your own risk.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ */
+
+/*
+ * sudo version 1.1 allows users to execute commands as root
+ * Copyright (C) 1991 The Root Group, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id: sudo.h,v 1.1 1996/10/14 05:14:54 millert Exp $
+ */
+
+#ifndef _SUDO_SUDO_H
+#define _SUDO_SUDO_H
+
+#include <pathnames.h>
+#include "compat.h"
+
+/*
+ * IP address and netmask pairs for checking against local interfaces.
+ */
+struct interface {
+ struct in_addr addr;
+ struct in_addr netmask;
+};
+
+/*
+ * 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;
+};
+
+/*
+ * Data structure describing a command in the
+ * sudoers file.
+ */
+struct sudo_command {
+ char *cmnd;
+ char *args;
+};
+
+
+extern struct matchstack *match;
+extern int top;
+
+#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)
+
+/*
+ * Structure containing command matches if "sudo -l" is used.
+ */
+struct command_match {
+ char *runas;
+ size_t runas_len;
+ size_t runas_size;
+ char *cmnd;
+ size_t cmnd_len;
+ size_t cmnd_size;
+ int nopasswd;
+};
+
+/*
+ * Structure containing Cmnd_Alias's if "sudo -l" is used.
+ */
+struct command_alias {
+ char *alias;
+ char *entries;
+ size_t entries_size;
+ size_t entries_len;
+};
+
+/*
+ * Maximum number of characters to log per entry. The syslogger
+ * will log this much, after that, it truncates the log line.
+ * We need this here to make sure that we continue with another
+ * syslog(3) call if the internal buffer is moe than 1023 characters.
+ */
+#ifndef MAXSYSLOGLEN
+# define MAXSYSLOGLEN 960
+#endif
+
+#define SLOG_SYSLOG 0x01
+#define SLOG_FILE 0x02
+#define SLOG_BOTH 0x03
+
+#define VALIDATE_OK 0x00
+#define VALIDATE_NO_USER 0x01
+#define VALIDATE_NOT_OK 0x02
+#define VALIDATE_OK_NOPASS 0x03
+#define VALIDATE_ERROR -1
+
+/*
+ * the arguments passed to log_error() are ANDed with GLOBAL_PROBLEM
+ * If the result is TRUE, the argv is NOT logged with the error message
+ */
+#define GLOBAL_PROBLEM 0x20
+#define ALL_SYSTEMS_GO 0x00
+#define GLOBAL_NO_PW_ENT ( 0x01 | GLOBAL_PROBLEM )
+#define GLOBAL_NO_SPW_ENT ( 0x02 | GLOBAL_PROBLEM )
+#define GLOBAL_NO_HOSTNAME ( 0x03 | GLOBAL_PROBLEM )
+#define GLOBAL_HOST_UNREGISTERED ( 0x04 | GLOBAL_PROBLEM )
+#define PASSWORD_NOT_CORRECT 0x05
+#define PASSWORDS_NOT_CORRECT 0x06
+#define NO_SUDOERS_FILE ( 0x07 | GLOBAL_PROBLEM )
+#define BAD_SUDOERS_FILE ( 0x08 | GLOBAL_PROBLEM )
+#define SUDOERS_WRONG_OWNER ( 0x09 | GLOBAL_PROBLEM )
+#define SUDOERS_WRONG_MODE ( 0x0A | GLOBAL_PROBLEM )
+#define SUDOERS_NOT_FILE ( 0x0B | GLOBAL_PROBLEM )
+#define SPOOF_ATTEMPT 0x0D
+#define BAD_STAMPDIR 0x0E
+#define BAD_STAMPFILE 0x0F
+
+/*
+ * Boolean values
+ */
+#undef TRUE
+#define TRUE 0x01
+#undef FALSE
+#define FALSE 0x00
+
+/*
+ * Various modes sudo can be in (based on arguments) in octal
+ */
+#define MODE_RUN 00001
+#define MODE_VALIDATE 00002
+#define MODE_KILL 00004
+#define MODE_VERSION 00010
+#define MODE_HELP 00020
+#define MODE_LIST 00040
+#define MODE_BACKGROUND 00100
+#define MODE_SHELL 00200
+#define MODE_RESET_HOME 00400
+
+/*
+ * Used with set_perms()
+ */
+#define PERM_ROOT 0x00
+#define PERM_USER 0x01
+#define PERM_FULL_USER 0x02
+#define PERM_SUDOERS 0x03
+#define PERM_RUNAS 0x04
+
+/*
+ * Shortcuts for user_pw_ent
+ */
+#define user_name (user_pw_ent -> pw_name)
+#define user_passwd (user_pw_ent -> pw_passwd)
+#define user_uid (user_pw_ent -> pw_uid)
+#define user_gid (user_pw_ent -> pw_gid)
+#define user_shell (user_pw_ent -> pw_shell)
+#define user_dir (user_pw_ent -> pw_dir)
+
+/*
+ * Function prototypes
+ */
+#define YY_DECL int yylex __P((void))
+
+#ifndef HAVE_STRDUP
+char *strdup __P((const char *));
+#endif
+#ifndef HAVE_GETWD
+char *getwd __P((char *));
+#endif
+#if !defined(HAVE_PUTENV) && !defined(HAVE_SETENV)
+int putenv __P((const char *));
+#endif
+char *sudo_goodpath __P((const char *));
+int sudo_setenv __P((char *, char *));
+char *tgetpass __P((char *, int, char *, char *));
+char * find_path __P((char *));
+void log_error __P((int));
+void inform_user __P((int));
+void check_user __P((void));
+int validate __P((int));
+void set_perms __P((int, int));
+void remove_timestamp __P((void));
+void load_interfaces __P((void));
+int yyparse __P((void));
+YY_DECL;
+
+
+/*
+ * Most of these variables are declared in main() so they don't need
+ * to be extern'ed here if this is main...
+ */
+#ifndef MAIN
+extern char host[];
+extern char *shost;
+extern char cwd[];
+extern struct interface *interfaces;
+extern int num_interfaces;
+extern struct passwd *user_pw_ent;
+extern char *runas_user;
+extern char *tty;
+extern char *cmnd;
+extern char *cmnd_args;
+extern char *prompt;
+extern struct stat cmnd_st;
+extern int Argc;
+extern char **Argv;
+extern int NewArgc;
+extern char **NewArgv;
+#endif
+extern int errno;
+
+#endif /* _SUDO_SUDO_H */
diff --git a/gnu/usr.bin/sudo/sudo/sudo_setenv.c b/gnu/usr.bin/sudo/sudo/sudo_setenv.c
new file mode 100644
index 00000000000..bcfca6be3df
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/sudo_setenv.c
@@ -0,0 +1,94 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ *******************************************************************
+ *
+ * This module contains sudo_setenv().
+ * sudo_setenv(3) adds a string of the form "var=val" to the environment.
+ *
+ * Todd C. Miller (millert@colorado.edu) Fri Jun 3 18:32:19 MDT 1994
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: sudo_setenv.c,v 1.1 1996/10/14 05:14:55 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+#include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+
+#include "sudo.h"
+#include <options.h>
+
+#ifndef STDC_HEADERS
+#ifdef HAVE_PUTENV
+extern int putenv __P((const char *));
+#endif /* HAVE_PUTENV */
+#ifdef HAVE_SETENV
+extern int setenv __P((char *, char *, int));
+#endif /* HAVE_SETENV */
+#endif /* !STDC_HEADERS */
+
+
+/**********************************************************************
+ *
+ * sudo_setenv()
+ *
+ * sudo_setenv() adds a string of the form "var=val" to the environment.
+ * If it is unable to expand the current environent it returns -1,
+ * else it returns 0.
+ */
+
+int sudo_setenv(var, val)
+ char *var;
+ char *val;
+{
+
+#ifdef HAVE_SETENV
+ return(setenv(var, val, 1));
+#else
+ char *envstring, *tmp;
+
+ envstring = tmp = (char *) malloc(strlen(var) + strlen(val) + 2);
+ if (envstring == NULL)
+ return(-1);
+
+ while ((*tmp++ = *var++))
+ ;
+
+ *(tmp-1) = '=';
+
+ while ((*tmp++ = *val++))
+ ;
+
+ return(putenv(envstring));
+#endif /* HAVE_SETENV */
+}
diff --git a/gnu/usr.bin/sudo/sudo/sudoers.5 b/gnu/usr.bin/sudo/sudo/sudoers.5
new file mode 100644
index 00000000000..bcc6137b366
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/sudoers.5
@@ -0,0 +1,435 @@
+.rn '' }`
+''' $RCSfile: sudoers.5,v $$Revision: 1.1 $$Date: 1996/10/14 05:14:55 $
+'''
+''' $Log: sudoers.5,v $
+''' Revision 1.1 1996/10/14 05:14:55 millert
+''' sudo 1.5.2
+'''
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.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 L' '
+.ds R' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds L' `
+.ds R' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH sudoers 5 "1.5.2" "7/Sep/96" "FILE FORMATS"
+.IX Title "sudoers 5"
+.UC
+.IX Name "sudoers - list of which users may execute what as root"
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" 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 ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.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 ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" 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 v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.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
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'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 v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. 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
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+.IX Header "NAME"
+sudoers \- list of which users may execute what as root
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+The \fIsudoers\fR file is composed of an optional host alias section,
+an optional command alias section and the user specification section.
+All command or host aliases need to start with their respective keywords
+(ie: Host_Alias, User_Alias, or Cmnd_Alias).
+If there are multiple occurrences of a user, the union of the entries
+will be used.
+.Sh "user specification format:"
+.IX Subsection "user specification format:"
+.PP
+.Vb 1
+\& user access_group [: access_group] ...
+.Ve
+.Vb 10
+\& access_group ::= host_type = [(user_list)] [NOPASSWD:] [op]cmnd_type
+\& [,[(user_list)] [NOPASSWD:] [op]cmnd_type] ...
+\& host_type ::= a lower-case hostname, netgroup, ip address,
+\& network number, network number/netmask,
+\& or host alias.
+\& user_list ::= comma-separated list of users, uids, or
+\& User_Aliases the user may run commands as
+\& (default is root).
+\& cmnd_type ::= a command OR a command alias.
+\& op ::= the logical "!" NOT operator.
+.Ve
+.Sh "host alias section format:"
+.IX Subsection "host alias section format:"
+.PP
+.Vb 1
+\& Host_Alias HOSTALIAS = host-list
+.Ve
+.Vb 4
+\& Host_Alias ::= a keyword.
+\& HOSTALIAS ::= an upper-case alias name.
+\& host-list ::= a comma separated list of hosts, netgroups,
+\& ip addresses, networks.
+.Ve
+.Sh "user alias section format:"
+.IX Subsection "user alias section format:"
+.PP
+.Vb 1
+\& User_Alias USERALIAS = user-list
+.Ve
+.Vb 3
+\& User_Alias ::= a keyword.
+\& USERALIAS ::= an upper-case alias name.
+\& user-list ::= a comma separated list of users, groups, netgroups.
+.Ve
+.Sh "command alias section format:"
+.IX Subsection "command alias section format:"
+.PP
+.Vb 1
+\& Cmnd_Alias CMNDALIAS = cmnd-list
+.Ve
+.Vb 3
+\& Cmnd_Alias ::= a keyword.
+\& CMNDALIAS ::= an upper-case alias name.
+\& cmnd-list ::= a comma separated list commands.
+.Ve
+.Sh "command specification:"
+.IX Subsection "command specification:"
+.PP
+.Vb 1
+\& path arg1 arg2 .. argn = command
+.Ve
+.Vb 2
+\& path ::= a fully qualified pathname.
+\& arg[1..n] ::= optional command line arguments.
+.Ve
+.Sh "wildcards (aka meta characters):"
+.IX Subsection "wildcards (aka meta characters):"
+\fBsudo\fR allows shell-style \fIwildcards\fR along with command arguments
+in the \fIsudoers\fR file. Wildcard matching is done via the \fB\s-1POSIX\s0\fR
+\f(CWfnmatch(3)\fR routine.
+.Ip "\f(CW*\fR" 8
+.IX Item "\f(CW*\fR"
+Matches any set of zero or more characters.
+.Ip "\f(CW?\fR" 8
+.IX Item "\f(CW?\fR"
+Matches any single character.
+.Ip "\f(CW[...]\fR" 8
+.IX Item "\f(CW[...]\fR"
+Matches any character in the specified range.
+.Ip "\f(CW[!...]\fR" 8
+.IX Item "\f(CW[!...]\fR"
+Matches any character \fBnot\fR in the specified range.
+.Ip "\f(CW\ex\fR" 8
+.IX Item "\f(CW\ex\fR"
+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".
+.Sh "exceptions to wildcard rules:"
+.IX Subsection "exceptions to wildcard rules:"
+The following exceptions apply to the above rules:
+.Ip "\f(CW""\fR" 8
+.IX Item "\f(CW""\fR"
+If the empty string \f(CW""\fR is the only command line argument in the
+\fIsudoers\fR entry it means that command may take \fBno\fR arguments.
+.Sh "other special characters and reserved words:"
+.IX Subsection "other special characters and reserved words:"
+Text after a pound sign (\fB#\fR) is considered a comment.
+Words that begin with a percent sign (\fB%\fR) are assumed to
+be \s-1UN\s0*X groups (%staff refers to users in the group \fIstaff\fR).
+Words that begin with a plus sign (\fB+\fR) are assumed to
+be netgroups (\fB+cshosts\fR refers to the netgroup \fIcshosts\fR).
+Long lines can be newline escaped with the backslash \fB\e\fR character.
+The reserved word \fB\s-1NOPASSWD\s0\fR indicates that a user need not
+enter a password for the command listed in that entry.
+.PP
+The reserved alias \fI\s-1ALL\s0\fR can be used for both {Host,User,Cmnd}_Alias.
+\fB\s-1DO\s0 \s-1NOT\s0\fR define an alias of \fI\s-1ALL\s0\fR, it will \fB\s-1NOT\s0\fR be used.
+Note that \fI\s-1ALL\s0\fR implies the entire universe of hosts/users/commands.
+You can subtract elements from the universe by using the syntax:
+ user host=\s-1ALL\s0,!\s-1ALIAS1\s0,!/etc/halt...
+Note that the \*(L"!\*(R" notation only works in a user's command list. You
+may not use it to subtract elements in a User_Alias, Host_Alias,
+Cmnd_Alias or user list.
+.PP
+Commands may have optional command line arguments. If they do,
+then the arguments in the \fIsudoers\fR file must exactly match those
+on the command line. It is also possible to have a command's
+arguments span multiple lines as long as the line continuance
+character \*(L"\e\*(R" is used. The following characters must be escaped
+with a \*(L"\e\*(R" if used in command arguments: \*(L",\*(R", \*(L":\*(R", \*(L"=\*(R", \*(L"\e\*(R".
+.SH "EXAMPLES"
+.IX Header "EXAMPLES"
+.PP
+.Vb 7
+\& # Host alias specification
+\& Host_Alias HUB=houdini:\e
+\& REMOTE=merlin,kodiakthorn,spirit
+\& Host_Alias SERVERS=houdini,merlin,kodiakthorn,spirit
+\& Host_Alias CUNETS=128.138.0.0/255.255.0.0
+\& Host_Alias CSNETS=128.138.243.0,128.138.204.0,\e
+\& 128.138.205.192
+.Ve
+.Vb 3
+\& # User alias specification
+\& User_Alias FULLTIME=millert,dowdy,mikef
+\& User_Alias PARTTIME=juola,mccreary,tor
+.Ve
+.Vb 6
+\& # Command alias specification
+\& Cmnd_Alias LPCS=/usr/etc/lpc,/usr/ucb/lprm
+\& Cmnd_Alias SHELLS=/bin/sh,/bin/csh,/bin/tcsh,/bin/ksh
+\& Cmnd_Alias SU=/bin/su
+\& Cmnd_Alias MISC=/bin/rm,/bin/cat:\e
+\& SHUTDOWN=/etc/halt,/etc/shutdown
+.Ve
+.Vb 14
+\& # User specification
+\& FULLTIME ALL=(ALL) NOPASSWD: ALL
+\& %wheel ALL=ALL
+\& PARTTIME ALL=ALL,!SHELLS,!SU
+\& +interns +openlabs=ALL,!SHELLS,!SU
+\& britt REMOTE=SHUTDOWN:ALL=LPCS
+\& jimbo CUNETS=/bin/su ?*,!/bin/su root
+\& nieusma SERVERS=SHUTDOWN,/etc/reboot:\e
+\& HUB=ALL,!SHELLS
+\& jill houdini=/etc/shutdown -[hr] now,MISC
+\& markm HUB=ALL,!MISC,!/etc/shutdown,!/etc/halt
+\& davehieb merlin=ALL:SERVERS=/etc/halt:\e
+\& kodiakthorn=NOPASSWD: ALL
+\& steve CSNETS= (operator) /usr/op_commands/
+.Ve
+.Sh "Host Alias specifications:"
+.IX Subsection "Host Alias specifications:"
+The are four \fIhost aliases\fR. The first actually contains
+two \fIaliases\fR. It sets \f(CWHUB\fR to be \f(CWhoudini\fR and \f(CWREMOTE\fR
+to the three machines \f(CWmerlin\fR, \f(CWkodiakthorn\fR and \f(CWspirit\fR.
+Similarly, \f(CWSERVERS\fR is set to the machines \f(CWhoudini\fR, \f(CWmerlin\fR,
+\f(CWkodiakthorn\fR and \f(CWspirit\fR. The \f(CWCSNETS\fR alias will match
+any host on the 128.138.243.0, 128.138.204.0, or 128.138.205.192
+nets. The \f(CWCUNETS\fR alias will match any host on the 128.138.0.0
+(class B) network. Note that these are \fBnetwork\fR addresses, not ip
+addresses. Unless an explicate netmask is given, the local \fInetmask\fR
+is used to determine whether or not the current host belongs to a network.
+.Sh "User Alias specifications:"
+.IX Subsection "User Alias specifications:"
+The two \fIuser aliases\fR simply groups the \f(CWFULLTIME\fR and
+\f(CWPARTTIME\fR folks into two separate aliases.
+.Sh "Command alias specifications:"
+.IX Subsection "Command alias specifications:"
+Command aliases are lists of commands with or without associated
+command line arguments. The entries above should be self-explanatory.
+.Sh "User specifications:"
+.IX Subsection "User specifications:"
+.Ip "\s-1FULLTIME\s0" 16
+.IX Item "\s-1FULLTIME\s0"
+Full-time sysadmins in the \f(CWFULLTIME\fR alias may run any
+command on any host as any user without a password.
+.Ip "%wheel" 16
+.IX Item "%wheel"
+Any user in the \s-1UN\s0*X group \f(CWwheel\fR may run any
+command on any host.
+.Ip "\s-1PARTTIME\s0" 16
+.IX Item "\s-1PARTTIME\s0"
+Part-time sysadmins in the \f(CWPARTTIME\fR alias may run any
+command except those in the \f(CWSHELLS\fR and \f(CWSU\fR aliases
+on any host.
+.Ip "+interns" 16
+.IX Item "+interns"
+Any user in the netgroup \f(CWinterns\fR may run any
+command except those in the \f(CWSHELLS\fR and \f(CWSU\fR aliases
+on any host that is in the \f(CWopenlabs\fR netgroup.
+.Ip "britt" 16
+.IX Item "britt"
+The user \f(CWbritt\fR may run commands in the \f(CWSHUTDOWN\fR alias
+on the \f(CWREMOTE\fR machines and commands in the \f(CWLPCS\fR alias
+on any machine.
+.Ip "jimbo" 16
+.IX Item "jimbo"
+The user \f(CWjimbo\fR may \f(CWsu\fR to any user save root on the
+machines on \f(CWCUNETS\fR (which is explicately listed as a class
+B network).
+.Ip "nieusma" 16
+.IX Item "nieusma"
+The user \f(CWnieusma\fR may run commands in the \f(CWSHUTDOWN\fR alias
+as well as \fI/etc/reboot\fR on the \f(CWSERVER\fR machines and
+any command except those in the \f(CWSHELLS\fR alias on the \f(CWHUB\fR
+machines.
+.Ip "jill" 16
+.IX Item "jill"
+The user \f(CWjill\fR may run \f(CW/etc/shutdown -h now\fR or
+\f(CW/etc/shutdown -r now\fR as well as the commands in the
+\f(CWMISC\fR alias on houdini.
+.Ip "markm" 16
+.IX Item "markm"
+The user \f(CWmarkm\fR may run any command on the \f(CWHUB\fR machines
+except \fI/etc/shutdown\fR, \fI/etc/halt\fR, and commands listed
+in the \f(CWMISC\fR alias.
+.Ip "davehieb" 16
+.IX Item "davehieb"
+The user \f(CWdavehieb\fR may run any command on \f(CWmerlin\fR,
+\fI/etc/halt\fR on the \f(CWSERVERS\fR. He may also run any command
+on \f(CWkodiakthorn\fR without giving a password.
+.Ip "steve" 16
+.IX Item "steve"
+The user \f(CWsteve\fR may run any command in the \fI/usr/op_commands/\fR
+directory as user \f(CWoperator\fR on the machines on \f(CWCSNETS\fR.
+.SH "CAVEATS"
+.IX Header "CAVEATS"
+The \fIsudoers\fR file should \fBalways\fR be edited by the \fBvisudo\fR
+command which locks the file and does grammatical checking. It is
+imperative that the \fIsudoers\fR be free of syntax errors since sudo
+will not run with a syntactically incorrect \fIsudoers\fR file.
+.SH "FILES"
+.IX Header "FILES"
+.PP
+.Vb 2
+\& /etc/sudoers file of authorized users.
+\& /etc/netgroup list of network groups.
+.Ve
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\fIsudo\fR\|(8), \fIvisudo\fR\|(8), \fIsu\fR\|(1), \fIfnmatch\fR\|(3).
+
+.rn }` ''
diff --git a/gnu/usr.bin/sudo/sudo/tgetpass.c b/gnu/usr.bin/sudo/sudo/tgetpass.c
new file mode 100644
index 00000000000..b8a198d7adc
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/tgetpass.c
@@ -0,0 +1,275 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ *******************************************************************
+ *
+ * This module contains tgetpass(), getpass(3) with a timeout.
+ * It should work on any OS that supports sgtty (4BSD), termio (SYSV),
+ * or termios (POSIX) line disciplines.
+ *
+ * Todd C. Miller Sun Jun 5 17:22:31 MDT 1994
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: tgetpass.c,v 1.1 1996/10/14 05:14:56 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#include <limits.h>
+#include <pwd.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_BSDTYPES_H
+#include <sys/bsdtypes.h>
+#endif /* HAVE_SYS_BSDTYPES_H */
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H */
+#include <sys/time.h>
+#include <signal.h>
+#include <fcntl.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#else
+#ifdef HAVE_TERMIO_H
+#include <termio.h>
+#else
+#include <sgtty.h>
+#include <sys/ioctl.h>
+#endif /* HAVE_TERMIO_H */
+#endif /* HAVE_TERMIOS_H */
+#if (SHADOW_TYPE == SPW_SECUREWARE)
+# ifdef __hpux
+# include <hpsecurity.h>
+# else
+# include <sys/security.h>
+# endif /* __hpux */
+# include <prot.h>
+#endif /* SPW_SECUREWARE */
+
+#include <pathnames.h>
+#include "compat.h"
+
+#ifndef TCSASOFT
+#define TCSASOFT 0
+#endif /* TCSASOFT */
+
+
+/******************************************************************
+ *
+ * tgetpass()
+ *
+ * this function prints a prompt and gets a password from /dev/tty
+ * or stdin. Echo is turned off (if possible) during password entry
+ * and input will time out based on the value of timeout.
+ */
+
+char * tgetpass(prompt, timeout, user, host)
+ const char *prompt;
+ int timeout;
+ char *user;
+ char *host;
+{
+#ifdef HAVE_TERMIOS_H
+ struct termios term;
+#else
+#ifdef HAVE_TERMIO_H
+ struct termio term;
+#else
+ struct sgttyb ttyb;
+#endif /* HAVE_TERMIO_H */
+#endif /* HAVE_TERMIOS_H */
+#ifdef POSIX_SIGNALS
+ sigset_t oldmask;
+ sigset_t mask;
+#else
+ int oldmask;
+#endif /* POSIX_SIGNALS */
+ int n, echo;
+ FILE *input, *output;
+ static char buf[_PASSWD_LEN + 1];
+ fd_set readfds;
+ struct timeval tv;
+ char *p;
+
+ /*
+ * mask out SIGINT and SIGTSTP, should probably just catch and deal.
+ */
+#ifdef POSIX_SIGNALS
+ (void) sigemptyset(&mask);
+ (void) sigaddset(&mask, SIGINT);
+ (void) sigaddset(&mask, SIGTSTP);
+ (void) sigprocmask(SIG_BLOCK, &mask, &oldmask);
+#else
+ oldmask = sigblock(sigmask(SIGINT)|sigmask(SIGTSTP));
+#endif
+
+ /*
+ * open /dev/tty for reading/writing if possible or use
+ * stdin and stderr instead.
+ */
+ if ((input = fopen(_PATH_TTY, "r+")) == NULL) {
+ input = stdin;
+ output = stderr;
+ (void) fflush(output);
+ } else {
+ output = input;
+ }
+
+ /*
+ * turn off echo
+ */
+#ifdef HAVE_TERMIOS_H
+ (void) tcgetattr(fileno(input), &term);
+ if ((echo = (term.c_lflag & ECHO))) {
+ term.c_lflag &= ~ECHO;
+ (void) tcsetattr(fileno(input), TCSAFLUSH|TCSASOFT, &term);
+ }
+#else
+#ifdef HAVE_TERMIO_H
+ (void) ioctl(fileno(input), TCGETA, &term);
+ if ((echo = (term.c_lflag & ECHO))) {
+ term.c_lflag &= ~ECHO;
+ (void) ioctl(fileno(input), TCSETA, &term);
+ }
+#else
+ (void) ioctl(fileno(input), TIOCGETP, &ttyb);
+ if ((echo = (ttyb.sg_flags & ECHO))) {
+ ttyb.sg_flags &= ~ECHO;
+ (void) ioctl(fileno(input), TIOCSETP, &ttyb);
+ }
+#endif /* HAVE_TERMIO_H */
+#endif /* HAVE_TERMIOS_H */
+
+ /* print the prompt */
+ if (prompt) {
+ p = (char *) prompt;
+ do {
+ /* expand %u -> username, %h -> host */
+ switch (*p) {
+ case '%': if (user && *(p+1) == 'u') {
+ (void) fputs(user, output);
+ p++;
+ break;
+ } else if (host && *(p+1) == 'h') {
+ (void) fputs(host, output);
+ p++;
+ break;
+ }
+
+ default: (void) fputc(*p, output);
+ }
+ } while (*(++p));
+ }
+
+ /* rewind if necesary */
+ if (input == output) {
+ (void) fflush(output);
+ (void) rewind(output);
+ }
+
+ /*
+ * Timeout of <= 0 means no timeout
+ */
+ if (timeout > 0) {
+ /* setup for select(2) */
+ FD_ZERO(&readfds);
+ FD_SET(fileno(input), &readfds);
+
+ /* set timeout for select */
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ /* how many file descriptors may we have? */
+#ifdef HAVE_SYSCONF
+ n = sysconf(_SC_OPEN_MAX);
+#else
+ n = getdtablesize();
+#endif /* HAVE_SYSCONF */
+
+ /*
+ * get password or return empty string if nothing to read by timeout
+ */
+ buf[0] = '\0';
+ if (select(n, &readfds, 0, 0, &tv) > 0 && fgets(buf, sizeof(buf), input)) {
+ n = strlen(buf);
+ if (buf[n - 1] == '\n')
+ buf[n - 1] = '\0';
+ }
+ } else {
+ buf[0] = '\0';
+ if (fgets(buf, sizeof(buf), input)) {
+ n = strlen(buf);
+ if (buf[n - 1] == '\n')
+ buf[n - 1] = '\0';
+ }
+ }
+
+ /* turn on echo */
+#ifdef HAVE_TERMIOS_H
+ if (echo) {
+ term.c_lflag |= ECHO;
+ (void) tcsetattr(fileno(input), TCSAFLUSH|TCSASOFT, &term);
+ }
+#else
+#ifdef HAVE_TERMIO_H
+ if (echo) {
+ term.c_lflag |= ECHO;
+ (void) ioctl(fileno(input), TCSETA, &term);
+ }
+#else
+ if (echo) {
+ ttyb.sg_flags |= ECHO;
+ (void) ioctl(fileno(input), TIOCSETP, &ttyb);
+ }
+#endif /* HAVE_TERMIO_H */
+#endif /* HAVE_TERMIOS_H */
+
+ /* rewind if necesary */
+ if (input == output) {
+ (void) fflush(output);
+ (void) rewind(output);
+ }
+
+ /* print a newline since echo is turned off */
+ (void) fputc('\n', output);
+
+ /* restore old signal mask */
+#ifdef POSIX_SIGNALS
+ (void) sigprocmask(SIG_SETMASK, &oldmask, NULL);
+#else
+ (void) sigsetmask(oldmask);
+#endif
+
+ /* close /dev/tty if that's what we opened */
+ if (input != stdin)
+ (void) fclose(input);
+
+ return(buf);
+}
diff --git a/gnu/usr.bin/sudo/sudo/version.h b/gnu/usr.bin/sudo/sudo/version.h
new file mode 100644
index 00000000000..6cb682af53c
--- /dev/null
+++ b/gnu/usr.bin/sudo/sudo/version.h
@@ -0,0 +1,28 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ * $Id: version.h,v 1.1 1996/10/14 05:14:56 millert Exp $
+ */
+
+#ifndef _SUDO_VERSION_H
+#define _SUDO_VERSION_H
+
+static char version[] = "1.5.2";
+
+#endif /* _SUDO_VERSION_H */
diff --git a/gnu/usr.bin/sudo/visudo/Makefile b/gnu/usr.bin/sudo/visudo/Makefile
new file mode 100644
index 00000000000..c19e408ed38
--- /dev/null
+++ b/gnu/usr.bin/sudo/visudo/Makefile
@@ -0,0 +1,23 @@
+# $OpenBSD: Makefile,v 1.1 1996/10/14 05:14:57 millert Exp $
+
+PROG= visudo
+MAN= visudo.8
+CFLAGS+=-I${.CURDIR}/../sudo -I.
+SRCS= y.tab.c lex.yy.c visudo.c
+CLEANFILES+=y.tab.c y.tab.h lex.yy.c
+
+LDADD= -lcompat
+DPADD= ${LIBCOMPAT}
+
+BINOWN= root
+BINMODE=111
+BINDIR?=/usr/sbin
+
+.include <bsd.prog.mk>
+
+lex.yy.c: ${.CURDIR}/../sudo/parse.lex
+ rm -f lex.yy.c
+ $(LEX) ${.CURDIR}/../sudo/parse.lex
+
+y.tab.c y.tab.h: ${.CURDIR}/../sudo/parse.yacc
+ $(YACC) -d ${.CURDIR}/../sudo/parse.yacc
diff --git a/gnu/usr.bin/sudo/visudo/visudo.8 b/gnu/usr.bin/sudo/visudo/visudo.8
new file mode 100644
index 00000000000..1a976177f42
--- /dev/null
+++ b/gnu/usr.bin/sudo/visudo/visudo.8
@@ -0,0 +1,266 @@
+.rn '' }`
+''' $RCSfile: visudo.8,v $$Revision: 1.1 $$Date: 1996/10/14 05:14:58 $
+'''
+''' $Log: visudo.8,v $
+''' Revision 1.1 1996/10/14 05:14:58 millert
+''' sudo 1.5.2
+'''
+'''
+.de Sh
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+.de Ip
+.br
+.ie \\n(.$>=3 .ne \\$3
+.el .ne 3
+.IP "\\$1" \\$2
+..
+.de Vb
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve
+.ft R
+
+.fi
+..
+'''
+'''
+''' Set up \*(-- to give an unbreakable dash;
+''' string Tr holds user defined translation string.
+''' Bell System Logo is used as a dummy character.
+'''
+.tr \(*W-|\(bv\*(Tr
+.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 L' '
+.ds R' '
+'br\}
+.el\{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds L' `
+.ds R' '
+.ds PI \(*p
+'br\}
+.\" If the F register is turned on, we'll generate
+.\" index entries out stderr for the following things:
+.\" TH Title
+.\" SH Header
+.\" Sh Subsection
+.\" Ip Item
+.\" X<> Xref (embedded
+.\" Of course, you have to process the output yourself
+.\" in some meaninful fashion.
+.if \nF \{
+.de IX
+.tm Index:\\$1\t\\n%\t"\\$2"
+..
+.nr % 0
+.rr F
+.\}
+.TH visudo 8 "1.5.2" "7/Sep/96" "MAINTENANCE COMMANDS"
+.IX Title "visudo 8"
+.UC
+.IX Name "visudo - edit the sudoers file"
+.if n .hy 0
+.if n .na
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.de CQ \" put $1 in typewriter font
+.ft CW
+'if n "\c
+'if t \\&\\$1\c
+'if n \\&\\$1\c
+'if n \&"
+\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+'.ft R
+..
+.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
+. \" AM - accent mark definitions
+.bd B 3
+. \" 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 ? ?
+. ds ! !
+. ds /
+. ds q
+.\}
+.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 ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
+. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
+.\}
+. \" 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 v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
+.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
+.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
+.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
+.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
+.ds oe o\h'-(\w'o'u*4/10)'e
+.ds Oe O\h'-(\w'O'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 v \h'-1'\o'\(aa\(ga'
+. ds _ \h'-1'^
+. ds . \h'-1'.
+. ds 3 3
+. 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
+. ds oe oe
+. ds Oe OE
+.\}
+.rm #[ #] #H #V #F C
+.SH "NAME"
+.IX Header "NAME"
+visudo \- edit the sudoers file
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+\fBvisudo\fR [ \fB\-V\fR ]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\fBvisudo\fR edits the \fIsudoers\fR file in a safe fashion, analogous to
+\fIvipw\fR\|(8). \fBvisudo\fR locks the \fIsudoers\fR file against multiple
+simultaneous edits, provides basic sanity checks, and checks
+for parse errors. If the \fIsudoers\fR file is currently being
+edited you will receive a message to try again later. In the
+default configuration, the \fIvi\fR\|(1) editor is used, but there is
+a compile time option to allow use of whatever editor the
+environmental variables \f(CWEDITOR\fR or \f(CWVISUAL\fR are set to.
+.PP
+\fBvisudo\fR parses the \fIsudoers\fR file after the edit and will
+not save the changes if there is a syntax error. Upon finding
+an error, a message will be printed stating the line \fInumber\fR\|(s)
+that the error occurred on and the user will receive the
+\*(L"What now?\*(R" prompt. At this point the user may enter \*(L"e\*(R"
+to re-edit the \fIsudoers\fR file, enter \*(L"x\*(R" to exit without
+saving the changes, or \*(L"q\*(R" to quit and save changes. The
+\*(L"q\*(R" option should be used with extreme care because if \fBvisudo\fR
+believes there to be a parse error, so will \fBsudo\fR and no one
+will be able to execute \fBsudo\fR again until the error is fixed.
+Any other command at this prompt will print a short help message.
+When editing the \fIsudoers\fR 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).
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+\fBvisudo\fR accepts the following command line option:
+.Ip "-V" 4
+.IX Item "-V"
+The \f(CW-V\fR (version) option causes \fBvisudo\fR to print the version number
+and exit.
+.SH "FILES"
+.IX Header "FILES"
+.PP
+.Vb 2
+\& /etc/sudoers file of authorized users.
+\& /etc/stmp lock file for visudo.
+.Ve
+.SH "ENVIRONMENT VARIABLES"
+.IX Header "ENVIRONMENT VARIABLES"
+The following are used only if \fBvisudo\fR was compiled with the
+\fIENV_EDITOR\fR option:
+.PP
+.Vb 2
+\& EDITOR Used by visudo as the editor to use.
+\& VISUAL Used by visudo if EDITOR is not set.
+.Ve
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Many people have worked on \fIsudo\fR over the years, this version of
+\fBvisudo\fR was written by:
+.PP
+.Vb 1
+\& Todd Miller <Todd.Miller@courtesan.com>
+.Ve
+See the HISTORY file in the sudo distribution for more details.
+.PP
+Please send all bugs, comments, and changes to sudo-bugs@courtesan.com.
+.SH "DISCLAIMER"
+.IX Header "DISCLAIMER"
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+.PP
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+675 Mass Ave, Cambridge, MA 02139, USA.
+.SH "CAVEATS"
+.IX Header "CAVEATS"
+Due to the syntax of the \fIsudoers\fR file, there is no way
+for \fBvisudo\fR to tell the difference between a mistyped
+{Host,User,Cmnd}_Alias and a user or host name.
+.PP
+There is no easy way to prevent a user from gaining a root shell if
+the editor used by \fBvisudo\fR allows shell escapes.
+.SH "BUGS"
+.IX Header "BUGS"
+The \fI\-V\fR flag gives the version of the \fIsudo\fR package rather than
+the individual \fBvisudo\fR program.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\fIsudo\fR\|(8), \fIvipw\fR\|(8).
+
+.rn }` ''
diff --git a/gnu/usr.bin/sudo/visudo/visudo.c b/gnu/usr.bin/sudo/visudo/visudo.c
new file mode 100644
index 00000000000..85099e75715
--- /dev/null
+++ b/gnu/usr.bin/sudo/visudo/visudo.c
@@ -0,0 +1,512 @@
+/*
+ * CU sudo version 1.5.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 1, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Please send bugs, changes, problems to sudo-bugs@courtesan.com
+ *
+ *******************************************************************
+ *
+ * visudo.c -- locks the sudoers file for safe editing and check
+ * for parse errors.
+ *
+ * Todd C. Miller (millert@colorado.edu) Sat Mar 25 21:50:36 MST 1995
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: visudo.c,v 1.1 1996/10/14 05:14:58 millert Exp $";
+#endif /* lint */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif /* STDC_HEADERS */
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+#include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#include <ctype.h>
+#include <pwd.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+
+#include "sudo.h"
+#include <options.h>
+#include "version.h"
+
+#ifndef STDC_HEADERS
+#ifndef __GNUC__ /* gcc has its own malloc */
+extern char *malloc __P((size_t));
+#endif /* __GNUC__ */
+extern char *getenv __P((const char *));
+extern int stat __P((const char *, struct stat *));
+#endif /* !STDC_HEADERS */
+
+#if defined(POSIX_SIGNALS) && !defined(SA_RESETHAND)
+#define SA_RESETHAND 0
+#endif /* POSIX_SIGNALS && !SA_RESETHAND */
+
+/*
+ * Function prototypes
+ */
+static void usage __P((void));
+static char whatnow __P((void));
+static void whatnow_help __P((void));
+static RETSIGTYPE Exit __P((int));
+static void setup_signals __P((void));
+int command_matches __P((char *, char *, char *, char *));
+int addr_matches __P((char *));
+int netgr_matches __P((char *, char *, char *));
+int usergr_matches __P((char *, char *));
+void init_parser __P((void));
+
+
+/*
+ * External globals
+ */
+extern FILE *yyin, *yyout;
+extern int errorlineno, sudolineno;
+
+
+/*
+ * Globals
+ */
+char **Argv;
+char **NewArgv = NULL;
+int NewArgc = 0;
+char *sudoers = _PATH_SUDO_SUDOERS;
+char *stmp = _PATH_SUDO_STMP;
+int parse_error = FALSE;
+char *runas_user = "root";
+
+/*
+ * For the parsing routines
+ */
+char host[] = "";
+char *shost = "";
+char *cmnd = "";
+char *cmnd_args = NULL;
+struct passwd *user_pw_ent;
+
+
+/********************************************************************
+ *
+ * main()
+ *
+ * where it all begins...
+ */
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char buf[BUFSIZ]; /* buffer used for copying files */
+ char * Editor = EDITOR; /* editor to use (default is EDITOR */
+ int sudoers_fd; /* sudoers file descriptor */
+ int stmp_fd; /* stmp file descriptor */
+ int n; /* length parameter */
+
+ (void) setbuf(stderr, (char *)NULL); /* unbuffered stderr */
+
+ /*
+ * Parse command line options
+ */
+ Argv = argv;
+
+ /*
+ * If passesd -V then print version, else print usage
+ * if any other option...
+ */
+ if (argc == 2)
+ if (!strcmp(Argv[1], "-V")) {
+ (void) printf("visudo version %s\n", version);
+ exit(0);
+ } else {
+ usage();
+ }
+ else if (argc != 1)
+ usage();
+
+ /* user_pw_ent needs to point to something... */
+ user_pw_ent = getpwuid(getuid());
+
+#ifdef ENV_EDITOR
+ /*
+ * If we are allowing EDITOR and VISUAL envariables set Editor
+ * base on whichever exists...
+ */
+ if (!(Editor = getenv("EDITOR")))
+ if (!(Editor = getenv("VISUAL")))
+ Editor = EDITOR;
+#endif /* ENV_EDITOR */
+
+ /*
+ * Copy sudoers file to stmp
+ */
+ stmp_fd = open(stmp, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ if (stmp_fd < 0) {
+ if (errno == EEXIST) {
+ (void) fprintf(stderr, "%s: sudoers file busy, try again later.\n",
+ Argv[0]);
+ exit(1);
+ }
+ (void) fprintf(stderr, "%s: ", Argv[0]);
+ perror(stmp);
+ Exit(1);
+ }
+
+ /* install signal handler to clean up stmp */
+ setup_signals();
+
+ sudoers_fd = open(sudoers, O_RDONLY);
+ if (sudoers_fd < 0) {
+ (void) fprintf(stderr, "%s: ", Argv[0]);
+ perror(sudoers);
+ Exit(1);
+ }
+
+ /*
+ * Copy the data
+ */
+ while ((n = read(sudoers_fd, buf, sizeof(buf))) > 0)
+ if (write(stmp_fd, buf, n) != n) {
+ (void) fprintf(stderr, "%s: Write failed: ", Argv[0]);
+ perror("");
+ Exit(1);
+ }
+
+ (void) close(sudoers_fd);
+ (void) close(stmp_fd);
+
+ /*
+ * Edit the temp file and parse it (for sanity checking)
+ */
+ do {
+ /*
+ * Build up a buffer to execute
+ */
+ if (parse_error == TRUE)
+ (void) sprintf(buf, "%s +%d %s", Editor, errorlineno, stmp);
+ else
+ (void) sprintf(buf, "%s %s", Editor, stmp);
+
+ /* do the edit -- some SYSV editors return 256 instead of 0 */
+ n = system(buf);
+ if (n == 0 || n == 256) {
+ struct stat statbuf; /* for sanity checking */
+
+ /* make sure stmp exists */
+ if (stat(stmp, &statbuf) < 0) {
+ (void) fprintf(stderr,
+ "%s: Can't stat temporary file (%s), %s unchanged.\n",
+ Argv[0], stmp, sudoers);
+ Exit(1);
+ }
+
+ /* check for zero length file */
+ if (statbuf.st_size == 0) {
+ (void) fprintf(stderr,
+ "%s: Zero length temporary file (%s), %s unchanged.\n",
+ Argv[0], stmp, sudoers);
+ Exit(1);
+ }
+
+ /*
+ * passed sanity checks so reopen stmp file and check
+ * for parse errors.
+ */
+ yyout = stdout;
+ if (parse_error)
+ yyin = freopen(stmp, "r", yyin);
+ else
+ yyin = fopen(stmp, "r");
+ if (yyin == NULL) {
+ (void) fprintf(stderr,
+ "%s: Can't re-open temporary file (%s), %s unchanged.\n",
+ Argv[0], stmp, sudoers);
+ Exit(1);
+ }
+
+ /* clean slate for each parse */
+ init_parser();
+
+ /* parse the sudoers file */
+ if (yyparse()) {
+ (void) fprintf(stderr,
+ "%s: Failed to parse temporary file (%s), %s unchanged.\n",
+ Argv[0], stmp, sudoers);
+ Exit(1);
+ }
+ } else {
+ (void) fprintf(stderr, "%s: Editor (%s) failed, %s unchanged.\n",
+ Argv[0], Editor, sudoers);
+ Exit(1);
+ }
+
+ /*
+ * Prompt the user for what to do now
+ */
+ if (parse_error == TRUE) {
+ switch (whatnow()) {
+ case 'q' : parse_error = FALSE; /* ignore parse error */
+ break;
+ case 'x' : Exit(0);
+ break;
+ }
+ }
+ } while (parse_error == TRUE);
+
+ /*
+ * Change mode and ownership of temp file so when
+ * we move it to sudoers things are kosher.
+ */
+ if (chown(stmp, SUDOERS_UID, SUDOERS_GID)) {
+ (void) fprintf(stderr,
+ "%s: Unable to set (uid, gid) of %s to (%d, %d): ",
+ Argv[0], stmp, SUDOERS_UID, SUDOERS_GID);
+ perror("");
+ Exit(1);
+ }
+ if (chmod(stmp, SUDOERS_MODE)) {
+ (void) fprintf(stderr,
+ "%s: Unable to change mode of %s to %o: ",
+ Argv[0], stmp, SUDOERS_MODE);
+ perror("");
+ Exit(1);
+ }
+
+ /*
+ * Now that we have a sane stmp file (parse ok) it needs to be
+ * rename(2)'d to sudoers. If the rename(2) fails we try using
+ * mv(1) in case stmp and sudoers are on different filesystems.
+ */
+ if (rename(stmp, sudoers))
+ if (errno == EXDEV) {
+ char *tmpbuf;
+
+ (void) fprintf(stderr,
+ "%s: %s and %s not on the same filesystem, using mv to rename.\n",
+ Argv[0], stmp, sudoers);
+
+ /* Allocate just enough space for tmpbuf */
+ n = sizeof(char) * (strlen(_PATH_MV) + strlen(stmp) +
+ strlen(sudoers) + 4);
+ if ((tmpbuf = (char *) malloc(n)) == NULL) {
+ (void) fprintf(stderr,
+ "%s: Cannot alocate memory, %s unchanged: ",
+ Argv[0], sudoers);
+ perror("");
+ Exit(1);
+ }
+
+ /* Build up command and execute it */
+ (void) sprintf(tmpbuf, "%s %s %s", _PATH_MV, stmp, sudoers);
+ if (system(tmpbuf)) {
+ (void) fprintf(stderr,
+ "%s: Command failed: '%s', %s unchanged.\n",
+ Argv[0], tmpbuf, sudoers);
+ Exit(1);
+ }
+ (void) free(tmpbuf);
+ } else {
+ (void) fprintf(stderr, "%s: Error renaming %s, %s unchanged: ",
+ Argv[0], stmp, sudoers);
+ perror("");
+ Exit(1);
+ }
+
+ return(0);
+}
+
+
+/********************************************************************
+ *
+ * dummy *_matches routines
+ *
+ * These exist to allow us to use the same parser as sudo(8).
+ */
+
+int command_matches(cmnd, user_args, path, sudoers_args)
+ char *cmnd;
+ char *user_args;
+ char *path;
+ char *sudoers_args;
+{
+ return(TRUE);
+}
+
+
+int addr_matches(n)
+ char *n;
+{
+ return(TRUE);
+}
+
+int usergr_matches(g, u)
+ char *g, *u;
+{
+ return(TRUE);
+}
+
+
+int netgr_matches(n, h, u)
+ char *n, *h, *u;
+{
+ return(TRUE);
+}
+
+
+/********************************************************************
+ *
+ * usage()
+ *
+ * Prints a help message and exits w/ exit value of 1.
+ */
+
+static void usage()
+{
+ (void) fprintf(stderr, "usage: %s [-V]\n", Argv[0]);
+ Exit(1);
+}
+
+
+/********************************************************************
+ *
+ * Exit()
+ *
+ * Unlinks the sudoers temp file (if it exists) and exits.
+ * Used in place of a normal exit() and as a signal handler.
+ */
+
+static RETSIGTYPE Exit(sig)
+ int sig;
+{
+ (void) unlink(stmp);
+ exit(sig);
+}
+
+
+/********************************************************************
+ *
+ * whatnow()
+ *
+ * Assuming a parse error occurred, prompt the user for what they want
+ * to do now. Returns first letter of their choice (always lowercase).
+ */
+
+static char whatnow()
+{
+ char choice;
+ int ok;
+
+ do {
+ ok = FALSE;
+ (void) printf("What now? ");
+ if ((choice = fgetc(stdin)) != '\n')
+ while (fgetc(stdin) != '\n')
+ ;
+
+ /* safely force to lower case */
+ if (isupper(choice))
+ choice = tolower(choice);
+
+ if (choice == 'e' || choice == 'x' || choice == 'q')
+ ok = TRUE;
+
+ /* help message if they gavce us garbage */
+ if (!ok)
+ whatnow_help();
+
+ } while (!ok);
+
+ return(choice);
+}
+
+
+/********************************************************************
+ *
+ * whatnow_help()
+ *
+ * Print out a help message for whatnow().
+ */
+
+static void whatnow_help()
+{
+ (void) printf("Options are:\n");
+ (void) printf(" (e)dit sudoers file again\n");
+ (void) printf(" e(x)it without saving changes to sudoers file\n");
+ (void) printf(" (q)uit and save changes to sudoers file (DANGER!)\n\n");
+}
+
+
+/********************************************************************
+ *
+ * setup_signals()
+ *
+ * Install signal handlers for visudo.
+ */
+
+static void setup_signals()
+{
+#ifdef POSIX_SIGNALS
+ struct sigaction action; /* posix signal structure */
+#endif /* POSIX_SIGNALS */
+
+ /*
+ * Setup signal handlers
+ */
+#ifdef POSIX_SIGNALS
+ (void) memset((VOID *)&action, 0, sizeof(action));
+ action.sa_handler = Exit;
+ action.sa_flags = SA_RESETHAND;
+ (void) sigaction(SIGILL, &action, NULL);
+ (void) sigaction(SIGTRAP, &action, NULL);
+ (void) sigaction(SIGBUS, &action, NULL);
+ (void) sigaction(SIGSEGV, &action, NULL);
+ (void) sigaction(SIGTERM, &action, NULL);
+
+ action.sa_handler = SIG_IGN;
+ action.sa_flags = 0;
+ (void) sigaction(SIGHUP, &action, NULL);
+ (void) sigaction(SIGINT, &action, NULL);
+ (void) sigaction(SIGQUIT, &action, NULL);
+#else
+ (void) signal(SIGILL, Exit);
+ (void) signal(SIGTRAP, Exit);
+ (void) signal(SIGBUS, Exit);
+ (void) signal(SIGSEGV, Exit);
+ (void) signal(SIGTERM, Exit);
+
+ (void) signal(SIGHUP, SIG_IGN);
+ (void) signal(SIGINT, SIG_IGN);
+ (void) signal(SIGQUIT, SIG_IGN);
+#endif /* POSIX_SIGNALS */
+}