From 2dfcbf193123fd16b26454eeffa4bbd014e52c53 Mon Sep 17 00:00:00 2001 From: pst Date: Thu, 6 Feb 1997 17:52:29 +0000 Subject: Initial import of OPIE v2.3 from ftp://ftp.nrl.navy.mil/pub/security/opie/ --- contrib/opie/BUG-REPORT | 81 + contrib/opie/COPYRIGHT.NRL | 68 + contrib/opie/INSTALL | 88 + contrib/opie/License.TIN | 45 + contrib/opie/Makefile.in | 271 +++ contrib/opie/README | 391 +++ contrib/opie/acconfig.h | 118 + contrib/opie/config.h.in | 324 +++ contrib/opie/config.testeflag | 12 + contrib/opie/configure | 4089 ++++++++++++++++++++++++++++++++ contrib/opie/configure.in | 455 ++++ contrib/opie/configure.munger.in | 16 + contrib/opie/ftpcmd.y | 1286 ++++++++++ contrib/opie/glob.c | 667 ++++++ contrib/opie/install-sh | 238 ++ contrib/opie/libmissing/Makefile.in | 30 + contrib/opie/libmissing/alloca.c | 494 ++++ contrib/opie/libmissing/bogus.c | 1 + contrib/opie/libmissing/endutent.c | 18 + contrib/opie/libmissing/env.c | 141 ++ contrib/opie/libmissing/getcwd.c | 23 + contrib/opie/libmissing/getusershell.c | 67 + contrib/opie/libmissing/getutline.c | 50 + contrib/opie/libmissing/initgroups.c | 129 + contrib/opie/libmissing/memcmp.c | 25 + contrib/opie/libmissing/memcpy.c | 25 + contrib/opie/libmissing/memset.c | 21 + contrib/opie/libmissing/pututline.c | 56 + contrib/opie/libmissing/sigaddset.c | 36 + contrib/opie/libmissing/sigemptyset.c | 23 + contrib/opie/libmissing/sigprocmask.c | 68 + contrib/opie/libmissing/strchr.c | 24 + contrib/opie/libmissing/strerror.c | 34 + contrib/opie/libmissing/strncasecmp.c | 30 + contrib/opie/libmissing/strrchr.c | 25 + contrib/opie/libmissing/sysconf.c | 30 + contrib/opie/libmissing/uname.c | 42 + contrib/opie/libopie/Makefile.in | 28 + contrib/opie/libopie/accessfile.c | 165 ++ contrib/opie/libopie/atob8.c | 74 + contrib/opie/libopie/btoa8.c | 32 + contrib/opie/libopie/btoe.c | 2266 ++++++++++++++++++ contrib/opie/libopie/btoh.c | 35 + contrib/opie/libopie/challenge.c | 74 + contrib/opie/libopie/generator.c | 110 + contrib/opie/libopie/getsequence.c | 27 + contrib/opie/libopie/getutmpentry.c | 72 + contrib/opie/libopie/hash.c | 52 + contrib/opie/libopie/hashlen.c | 51 + contrib/opie/libopie/insecure.c | 146 ++ contrib/opie/libopie/keycrunch.c | 64 + contrib/opie/libopie/lock.c | 175 ++ contrib/opie/libopie/login.c | 130 + contrib/opie/libopie/lookup.c | 30 + contrib/opie/libopie/md4c.c | 267 +++ contrib/opie/libopie/md5c.c | 304 +++ contrib/opie/libopie/newseed.c | 99 + contrib/opie/libopie/open.c | 61 + contrib/opie/libopie/parsechallenge.c | 70 + contrib/opie/libopie/passcheck.c | 50 + contrib/opie/libopie/passwd.c | 74 + contrib/opie/libopie/randomchallenge.c | 43 + contrib/opie/libopie/readpass.c | 304 +++ contrib/opie/libopie/readrec.c | 218 ++ contrib/opie/libopie/unlock.c | 103 + contrib/opie/libopie/verify.c | 255 ++ contrib/opie/libopie/version.c | 27 + contrib/opie/libopie/writerec.c | 85 + contrib/opie/logwtmp.c | 154 ++ contrib/opie/opie.4 | 346 +++ contrib/opie/opie.h | 224 ++ contrib/opie/opie_cfg.h | 167 ++ contrib/opie/opieaccess.5 | 87 + contrib/opie/opieftpd.8 | 280 +++ contrib/opie/opieftpd.c | 1643 +++++++++++++ contrib/opie/opiegen.1 | 88 + contrib/opie/opiegen.c | 88 + contrib/opie/opieinfo.1 | 99 + contrib/opie/opieinfo.c | 90 + contrib/opie/opiekey.1 | 173 ++ contrib/opie/opiekey.c | 375 +++ contrib/opie/opiekeys.5 | 66 + contrib/opie/opielogin.1 | 131 + contrib/opie/opielogin.c | 1428 +++++++++++ contrib/opie/opiepasswd.1 | 176 ++ contrib/opie/opiepasswd.c | 429 ++++ contrib/opie/opieserv.1 | 82 + contrib/opie/opieserv.c | 83 + contrib/opie/opiesu.1 | 101 + contrib/opie/opiesu.c | 448 ++++ contrib/opie/opietest.c | 255 ++ contrib/opie/options.h | 85 + contrib/opie/permsfile.c | 163 ++ contrib/opie/popen.c | 204 ++ 94 files changed, 22497 insertions(+) create mode 100644 contrib/opie/BUG-REPORT create mode 100644 contrib/opie/COPYRIGHT.NRL create mode 100644 contrib/opie/INSTALL create mode 100644 contrib/opie/License.TIN create mode 100644 contrib/opie/Makefile.in create mode 100644 contrib/opie/README create mode 100644 contrib/opie/acconfig.h create mode 100644 contrib/opie/config.h.in create mode 100644 contrib/opie/config.testeflag create mode 100755 contrib/opie/configure create mode 100644 contrib/opie/configure.in create mode 100644 contrib/opie/configure.munger.in create mode 100644 contrib/opie/ftpcmd.y create mode 100644 contrib/opie/glob.c create mode 100644 contrib/opie/install-sh create mode 100644 contrib/opie/libmissing/Makefile.in create mode 100644 contrib/opie/libmissing/alloca.c create mode 100644 contrib/opie/libmissing/bogus.c create mode 100644 contrib/opie/libmissing/endutent.c create mode 100644 contrib/opie/libmissing/env.c create mode 100644 contrib/opie/libmissing/getcwd.c create mode 100644 contrib/opie/libmissing/getusershell.c create mode 100644 contrib/opie/libmissing/getutline.c create mode 100644 contrib/opie/libmissing/initgroups.c create mode 100644 contrib/opie/libmissing/memcmp.c create mode 100644 contrib/opie/libmissing/memcpy.c create mode 100644 contrib/opie/libmissing/memset.c create mode 100644 contrib/opie/libmissing/pututline.c create mode 100644 contrib/opie/libmissing/sigaddset.c create mode 100644 contrib/opie/libmissing/sigemptyset.c create mode 100644 contrib/opie/libmissing/sigprocmask.c create mode 100644 contrib/opie/libmissing/strchr.c create mode 100644 contrib/opie/libmissing/strerror.c create mode 100644 contrib/opie/libmissing/strncasecmp.c create mode 100644 contrib/opie/libmissing/strrchr.c create mode 100644 contrib/opie/libmissing/sysconf.c create mode 100644 contrib/opie/libmissing/uname.c create mode 100644 contrib/opie/libopie/Makefile.in create mode 100644 contrib/opie/libopie/accessfile.c create mode 100644 contrib/opie/libopie/atob8.c create mode 100644 contrib/opie/libopie/btoa8.c create mode 100644 contrib/opie/libopie/btoe.c create mode 100644 contrib/opie/libopie/btoh.c create mode 100644 contrib/opie/libopie/challenge.c create mode 100644 contrib/opie/libopie/generator.c create mode 100644 contrib/opie/libopie/getsequence.c create mode 100644 contrib/opie/libopie/getutmpentry.c create mode 100644 contrib/opie/libopie/hash.c create mode 100644 contrib/opie/libopie/hashlen.c create mode 100644 contrib/opie/libopie/insecure.c create mode 100644 contrib/opie/libopie/keycrunch.c create mode 100644 contrib/opie/libopie/lock.c create mode 100644 contrib/opie/libopie/login.c create mode 100644 contrib/opie/libopie/lookup.c create mode 100644 contrib/opie/libopie/md4c.c create mode 100644 contrib/opie/libopie/md5c.c create mode 100644 contrib/opie/libopie/newseed.c create mode 100644 contrib/opie/libopie/open.c create mode 100644 contrib/opie/libopie/parsechallenge.c create mode 100644 contrib/opie/libopie/passcheck.c create mode 100644 contrib/opie/libopie/passwd.c create mode 100644 contrib/opie/libopie/randomchallenge.c create mode 100644 contrib/opie/libopie/readpass.c create mode 100644 contrib/opie/libopie/readrec.c create mode 100644 contrib/opie/libopie/unlock.c create mode 100644 contrib/opie/libopie/verify.c create mode 100644 contrib/opie/libopie/version.c create mode 100644 contrib/opie/libopie/writerec.c create mode 100644 contrib/opie/logwtmp.c create mode 100644 contrib/opie/opie.4 create mode 100644 contrib/opie/opie.h create mode 100644 contrib/opie/opie_cfg.h create mode 100644 contrib/opie/opieaccess.5 create mode 100644 contrib/opie/opieftpd.8 create mode 100644 contrib/opie/opieftpd.c create mode 100644 contrib/opie/opiegen.1 create mode 100644 contrib/opie/opiegen.c create mode 100644 contrib/opie/opieinfo.1 create mode 100644 contrib/opie/opieinfo.c create mode 100644 contrib/opie/opiekey.1 create mode 100644 contrib/opie/opiekey.c create mode 100644 contrib/opie/opiekeys.5 create mode 100644 contrib/opie/opielogin.1 create mode 100644 contrib/opie/opielogin.c create mode 100644 contrib/opie/opiepasswd.1 create mode 100644 contrib/opie/opiepasswd.c create mode 100644 contrib/opie/opieserv.1 create mode 100644 contrib/opie/opieserv.c create mode 100644 contrib/opie/opiesu.1 create mode 100644 contrib/opie/opiesu.c create mode 100644 contrib/opie/opietest.c create mode 100644 contrib/opie/options.h create mode 100644 contrib/opie/permsfile.c create mode 100644 contrib/opie/popen.c (limited to 'contrib') diff --git a/contrib/opie/BUG-REPORT b/contrib/opie/BUG-REPORT new file mode 100644 index 0000000..813b388 --- /dev/null +++ b/contrib/opie/BUG-REPORT @@ -0,0 +1,81 @@ +OPIE Software Distribution, Release 2.3 Bug Reporting Form +======================================= ================== + + Please make a copy of this file and then edit it with your favorite +text editor to include the answers to the following questions: + +1. Your name and electronic mail address, in case we need more information. + If you can provide multiple addresses, please do so in case we + are unable to reply to the first one. + +2. Your exact operating system vendor, name, and version number. + Please be more specific than "UNIX" -- most vendors have a name + for their particular flavor of UNIX. + +3. The exact hardware the system was installed upon. + +4. Which compiler and C runtime you used and its version number. + For instance, some systems have been known to have the GNU libc + installed as well as its native one, or to have a "BSD + compatibility" environment. + +5. What version of OPIE you are using (the output of opiepasswd -v) and, + if you used the Autoconf install, a copy of the config.h, config.log, + and Makefile that Autoconf created. + +6. A clear description of what you did and what bug then appeared. + If your system has the script(1) command, please run a session + under that to demonstrate the bug. Window-system cut-and-paste + also works well. Sometimes, the exact output is critical to + finding the bug. + +If you can provide any of the following things, it will greatly assist +us in fixing the problem and improve the chances that we'll get back to you: + +7. A diagnosis of what is causing the problem. + +8. A test case that can repeatably demonstrate the problem. + +9. A fix for the problem. + + Bug reports should be sent by Internet electronic mail to +. This mail is run through an automated sorter that helps +get the bug report into the hands of someone who can help you. In order to +make that program work, we ask that you: + + * Send this is normal RFC822 plain text or MIME text/plain. + + * DO NOT send this or any other file as an "attachment" from + your mailer. + + * DO NOT send a copy of your bug report to ANYONE other than + . This includes listing more than one recipient + or sending it as a carbon-copy ("Cc:") to someone else. + + * DO NOT send a copy of your bug report directly to the + authors or to any mailing lists. This really makes the + authors angry, and will be interpreted as a request to not + provide you with any help. + + * DO NOT re-send bug reports because you didn't receive a + response. We attempt to respond to ALL properly submitted + bug reports. If we can't send mail back to you or you + didn't bother to follow the directions for submitting a + bug report, you won't receive a response. + + While OPIE is NOT a supported program, we generally try to respond +to all properly submitted bug reports as soon as we can. If your bug report +is properly submitted so our machine sorter can process it, this usually +takes one working day. If our machine sorter can't process your bug report, +it usually takes a week or two. + +Copyright +========= + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + diff --git a/contrib/opie/COPYRIGHT.NRL b/contrib/opie/COPYRIGHT.NRL new file mode 100644 index 0000000..cfbffc3 --- /dev/null +++ b/contrib/opie/COPYRIGHT.NRL @@ -0,0 +1,68 @@ +# @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 + +COPYRIGHT NOTICE + +All of the documentation and software included in this software +distribution from the US Naval Research Laboratory (NRL) are +copyrighted by their respective developers. + +Portions of the software are derived from the Net/2 and 4.4 Berkeley +Software Distributions (BSD) of the University of California at +Berkeley and those portions are copyright by The Regents of the +University of California. All Rights Reserved. The UC Berkeley +Copyright and License agreement is binding on those portions of the +software. In all cases, the NRL developers have retained the original +UC Berkeley copyright and license notices in the respective files in +accordance with the UC Berkeley copyrights and license. + +Portions of this software and documentation were developed at NRL by +various people. Those developers have each copyrighted the portions +that they developed at NRL and have assigned All Rights for those +portions to NRL. Outside the USA, NRL has copyright on some of the +software developed at NRL. The affected files all contain specific +copyright notices and those notices must be retained in any derived +work. + +NRL LICENSE + +NRL grants permission for redistribution and use in source and binary +forms, with or without modification, of the software and documentation +created at NRL provided that the following conditions are met: + +1. All terms of the UC Berkeley copyright and license must be followed. +2. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +3. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +4. All advertising materials mentioning features or use of this software + must display the following acknowledgements: + + This product includes software developed by the University of + California, Berkeley and its contributors. + + This product includes software developed at the Information + Technology Division, US Naval Research Laboratory. + +5. Neither the name of the NRL nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation +are those of the authors and should not be interpreted as representing +official policies, either expressed or implied, of the US Naval +Research Laboratory (NRL). + +---------------------------------------------------------------------- diff --git a/contrib/opie/INSTALL b/contrib/opie/INSTALL new file mode 100644 index 0000000..8551cb5 --- /dev/null +++ b/contrib/opie/INSTALL @@ -0,0 +1,88 @@ +OPIE Software Distribution, Release 2.3 Installation Instructions +======================================= ========================= + + Did you read the README file? + + If not, please go do so, then come back here. There is information in +the README file that you will probably need to know in order to build and use +OPIE, and you are better off doing it before you try to compile and install +it. + + OPIE uses Autoconf to automagically figure out as much as possible +about your system. There are four steps to installing OPIE. Please read them +all first before attempting to do them. + +1. Run the "configure" script. + + Normally, you will need to type: + + sh configure + + If you would like to use an access file to allow users from some hosts +to log into your system without using OTPs (thus opening up a big security +hole, but a necessary evil for some sites), type: + + sh configure --enable-access-file=/etc/opieaccess + + If you'd like the file to go somewhere else, adjust this appropriately. + +2. Edit the Makefile + + The Makefile contains some options that you may wish to modify. Also +verify that Autoconf chose the correct options for your system. + + The Makefile created by Autoconf should be correct for most users +as-is. + +3. Edit options.h + + Most user-tweakable options are specified in this file. + + The defaults should be reasonable for most users. + +4. Build OPIE + + Normally, you will need to type: + + make + + If you only want to build the client programs, type: + + make client + + If you only want to build the server programs, type: + + make server + +5. Verify that OPIE works on your system and install + + Normall, you will need to type: + + make install + + If you only want to install the client programs, type: + + make client-install + + If you only want to install the server programs, type: + + make server-install + + If you encounter any problems, you may be able to run "make uninstall" +to remove the OPIE software from your system and revert back to almost the +way things were before. + +Copyright +========= + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this document are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. diff --git a/contrib/opie/License.TIN b/contrib/opie/License.TIN new file mode 100644 index 0000000..0ec9d21 --- /dev/null +++ b/contrib/opie/License.TIN @@ -0,0 +1,45 @@ +The Inner Net License, Version 2 +================================ + + The author(s) grant permission for redistribution and use in source and +binary forms, with or without modification, of the software and documentation +provided that the following conditions are met: + +0. If you receive a version of the software that is specifically labelled + as not being for redistribution (check the version message and/or README), + you are not permitted to redistribute that version of the software in any + way or form. +1. All terms of the all other applicable copyrights and licenses must be + followed. +2. Redistributions of source code must retain the authors' copyright + notice(s), this list of conditions, and the following disclaimer. +3. Redistributions in binary form must reproduce the authors' copyright + notice(s), this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. +4. All advertising materials mentioning features or use of this software + must display the following acknowledgement with the name(s) of the + authors as specified in the copyright notice(s) substituted where + indicated: + + This product includes software developed by , The Inner + Net, and other contributors. + +5. Neither the name(s) of the author(s) nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Please distribute a copy of this license with the software and make it +reasonably easy for others to find. + + If these license terms cause you a real problem, contact the author. diff --git a/contrib/opie/Makefile.in b/contrib/opie/Makefile.in new file mode 100644 index 0000000..8c7b96d --- /dev/null +++ b/contrib/opie/Makefile.in @@ -0,0 +1,271 @@ +## +# Makefile.source and Makefile: Directions for building and installing OPIE. +# +# %%% portions-copyright-cmetz +# Portions of this software are Copyright 1996 by Craig Metz, All Rights +# Reserved. The Inner Net License Version 2 applies to these portions of +# the software. +# You should have received a copy of the license with this software. If +# you didn't get a copy, you may request one from . +# +# Portions of this software are Copyright 1995 by Randall Atkinson and Dan +# McDonald, All Rights Reserved. All Rights under this copyright are assigned +# to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +# License Agreement applies to this software. +# +# History: +# +# Modified by cmetz for OPIE 2.3. Removed manual config -- it's +# Autoconf or bust. Replaced user configuration options +# with options.h. Eliminated unused variables. Pass down +# $(DEBUG) instead of several other variables to the +# subdirs. Extended/standard key file support. Added +# dependencies on subdir files. Made opietest call silent. +# Removed opie-md4, opie-md5, and key aliases. Removed +# test target. Make uninstall remove man page aliases. +# Modified by cmetz for OPIE 2.22. Removed @LIBOBJS@ from MISSING for +# Autoconf target. Re-ordered LFLAGS because some ld's won't +# include libmissing properly if it's not at the end. +# Modified by cmetz for OPIE 2.21. Added getusershell.o to IRIX +# missing functions. +# Modified by cmetz for OPIE 2.2. Added NEW_PROMPTS definition. +# Added MISSING and new flags-passing for libmissing. +# Quote MISSING or lose. Update TEST target for FTPD +# variable. Removed line formatting for compile commands +# since macro expansion confuses the issue anyway. +# Added targets for opieserv. Added targets for opietest. +# Removed obselete options.h target. Swapped libmissing +# and libopie. Updated manual config options. Added more +# explanatory text. Fixed uses of old SYSV and BSD4_3 +# symbols. +# Modified at NRL for OPIE 2.2: Renamed LDFLAGS setting to LIBS, +# renamed LDFLAGS in targets to LFLAGS. Added targets for +# libopie and libmissing directories. Got rid of PROTOTYPES. +# Added opiegen. Fixed RANLIB Autoconf target. +# Modified at NRL for OPIE 2.11: Fixed fatal mistype of Autoconf. +# Modified at NRL for OPIE 2.1: Changed targets to reflect source +# file name changes. Changed explanation and flags for static +# linking. Changed opieinfo target. Removed WHOAMI. Added +# Autoconf targets. Changed if conditionals to use test +# instead of [. Changed SU_DIR to SU to help autoconf. +# Changed FTPDIR and FTPDNAME to FTPD to help autoconf. +# Changed HP-UX to HP-UX9 and HP-UX10. Make uninstall +# target depend on config. HPUX *is* no longer necessary, but +# something does have to be there. Sub in Autoconf @CC@. +# Modified at NRL for OPIE 2.04: Re-worded explanation of SU_STAR_CHECK. +# Modified at NRL for OPIE 2.02: Added SU_STAR_CHECK flag. +# Modified at NRL for OPIE 2.01: Test target makes opiesu and opielogin +# setuid. install target clears that. uninstall target needs to +# remove the opiekey symlinks. opieinfo target needs to +# substitute for $(EXISTS). ifdefs target needs to check for +# starting hash. $(LFLAGS) and -o should be at the end of all +# link commands to spoon-feed drain bamaged link editors. Added +# A/UX defaults. +# Modified heavily at NRL for OPIE 2.0. +# Written at Bellcore for the S/Key Version 1 software distribution +# (Makefile). + +#============================================================================ +# CONFIGURATION PARAMETERS -- CHANGE THESE TO SUIT YOUR MACHINE + +# Shell to use for make(1) +# It's usually a good idea to leave this as-is. On some systems, ksh or bash +# may be necessary +SHELL=/bin/sh + +# OWNER is the username who should own the OPIE binaries. +# GROUP is the groupname associated with the OPIE binaries. +# +OWNER=0 +GROUP=bin + +# Where should the OPIE standard and extended databases be stored? +# +# Some sites might want to put this elsewhere. If you want to use an old +# S/Key database, you should create a link from /etc/skeykeys to /etc/opiekeys. +STD_KEY_FILE=/etc/opiekeys +EXT_KEY_FILE=/etc/opiekeys.ext + +# Are we debugging? +# +# The first line will build a normal version of OPIE. You should use it. +# +# The second is for brave souls porting OPIE to a new system or trying to +# debug it and should definitely NOT be used to build a production copy +# of OPIE. +# +# The third is the above using nifty heap debugger called "Electric Fence". +DEBUG=-O +#DEBUG=-DDEBUG=1 -g +#DEBUG=-DDEBUG=1 -g -lefence + +# These parameters are determined by Autoconf and are probably correct. +# If OPIE doesn't build or work right, try tweaking these. +CC=@CC@ +YACC=@YACC@ +FTPD=@FTPD@ +LIBS=@LIBS@ +OPTIONS=@DEFS@ +EXISTS=@EXISTS@ +MKDIR=@MKDIR@ +CHOWN=@CHOWN@ +LOCALBIN=@LOCALBIN@ +LOCALMAN=@LOCALMAN@ +SU=@SU@ +ALT_SU=@ALT_SU@ +LOGIN=@LOGIN@ + +BACKUP=opie.old + +CFLAGS=$(DEBUG) + +LFLAGS=-Llibopie -Llibmissing -lopie $(LIBS) -lmissing -lopie +LDEPS=libmissing/libmissing.a libopie/libopie.a + +all: client server + +ifdefs: + egrep '^#*if*def' *.c *.h | cut -f2 -d: | sort | uniq + +client: libopie/libopie.a libmissing/libmissing.a opietest-passed opiekey opiegen + +client-install: client + @echo "Installing OPIE client software..." + @echo "Copying OPIE key-related files" + @if test ! -d $(LOCALBIN); then $(MKDIR) $(LOCALBIN); chmod 755 $(LOCALBIN); fi + @cp opiekey $(LOCALBIN) + @$(CHOWN) $(OWNER) $(LOCALBIN)/opiekey + @chgrp $(GROUP) $(LOCALBIN)/opiekey + @echo "Changing file permissions" + @chmod 0511 $(LOCALBIN)/opiekey + @echo "Symlinking aliases to opiekey" + @-ln -s $(LOCALBIN)/opiekey $(LOCALBIN)/otp-md4 + @-ln -s $(LOCALBIN)/opiekey $(LOCALBIN)/otp-md5 + @echo "Installing manual pages" + @-for i in otp-md4 otp-md5; do ln -s opiekey.1 $(LOCALMAN)/man1/$$i.1; done + @if test ! -d $(LOCALMAN)/man1; then $(MKDIR) $(LOCALMAN)/man1; chmod 755 $(LOCALMAN)/man1; fi; cp opiekey.1 $(LOCALMAN)/man1/opiekey.1; $(CHOWN) $(OWNER) $(LOCALMAN)/man1/opiekey.1; chgrp $(GROUP) $(LOCALMAN)/man1/opiekey.1; chmod 644 $(LOCALMAN)/man1/opiekey.1 + +server: libopie/libopie.a libmissing/libmissing.a opietest-passed opielogin opiesu opiepasswd opieinfo opieftpd opieserv + +server-install: server + @echo "Installing OPIE server software..." + @echo "Copying OPIE user programs" + @if test ! -d $(LOCALBIN); then $(MKDIR) $(LOCALBIN); chmod 755 $(LOCALBIN); fi + @cp opiepasswd opieinfo $(LOCALBIN) + @echo "Changing ownership" + @$(CHOWN) $(OWNER) $(LOCALBIN)/opiepasswd $(LOCALBIN)/opieinfo + @chgrp $(GROUP) $(LOCALBIN)/opiepasswd $(LOCALBIN)/opieinfo + @echo "Changing file permissions" + @chmod 0555 $(LOCALBIN)/opieinfo + @chmod 4511 $(LOCALBIN)/opiepasswd + @echo "Installing OPIE system programs..." + @if test ! $(EXISTS) $(LOGIN).$(BACKUP); then echo "Renaming existing $(LOGIN) to $(LOGIN).$(BACKUP)"; mv $(LOGIN) $(LOGIN).$(BACKUP); echo "Clearing permissions on old $(LOGIN)"; chmod 0 $(LOGIN).$(BACKUP); fi + @echo "Copying opielogin to $(LOGIN)" + @cp opielogin $(LOGIN) + @echo "Changing ownership of $(LOGIN)" + @$(CHOWN) $(OWNER) $(LOGIN) + @chgrp $(GROUP) $(LOGIN) + @echo "Changing file permissions of $(LOGIN)" + @chmod 4111 $(LOGIN) + @if test ! $(EXISTS) $(SU).$(BACKUP); then echo "Renaming existing su to su.$(BACKUP)"; mv $(SU) $(SU).$(BACKUP); echo "Clearing permissions on old su"; chmod 0 $(SU).$(BACKUP); fi + @-if test ! -z "$(ALT_SU)"; then if test ! $(EXISTS) $(ALT_SU).$(BACKUP); then echo "Renaming existing su to su.$(BACKUP)"; mv $(ALT_SU) $(ALT_SU).$(BACKUP); fi; echo "Copying opiesu to su"; cp opiesu $(ALT_SU); echo "Changing ownership"; $(CHOWN) $(OWNER) $(ALT_SU); chgrp $(GROUP) $(ALT_SU); echo "Changing file permissions"; chmod 4111 $(ALT_SU); echo "Clearning permissions on old su"; chmod 0 $(ALT_SU).$(BACKUP); fi + @echo "Copying opiesu to su" + @cp opiesu $(SU) + @echo "Changing ownership of su" + @$(CHOWN) $(OWNER) $(SU) + @chgrp $(GROUP) $(SU) + @echo "Changing file permissions of su" + @chmod 4111 $(SU) + @if test ! $(EXISTS) $(FTPD).$(BACKUP); then echo "Renaming existing ftp daemon to $(FTPD).$(BACKUP)"; mv $(FTPD) $(FTPD).$(BACKUP); echo "Clearing permissions on old ftp daemon"; chmod 0 $(FTPD).$(BACKUP); fi + @echo "Copying OPIE ftp daemon" + @cp opieftpd $(FTPD) + @echo "Changing ownership of ftpd" + @$(CHOWN) $(OWNER) $(FTPD) + @chgrp $(GROUP) $(FTPD) + @echo "Changing file permissions of ftpd" + @chmod 0100 $(FTPD) + @echo "Making sure OPIE database files exist" + @touch $(STD_KEY_FILE) $(EXT_KEY_FILE) + @echo "Changing permissions of OPIE database files" + @chmod 0644 $(STD_KEY_FILE) + @chmod 0600 $(EXT_KEY_FILE) + @echo "Changing ownership of OPIE database files" + @$(CHOWN) $(OWNER) $(STD_KEY_FILE) $(EXT_KEY_FILE) + @chgrp $(GROUP) $(STD_KEY_FILE) $(EXT_KEY_FILE) + @-if test ! -z "$(ACCESS_FILE)"; then echo "Creating OPIE access file (don't say we didn't warn you)"; FILE=`echo $(ACCESS_FILE) | sed 's:^-DACCESS_FILE="\(.*\)":\1:'`; touch $$FILE; $(CHOWN) 0 $$FILE; chgrp 0 $$FILE; chmod 0444 $$FILE; fi; + @echo "Installing manual pages" + @if test ! -d $(LOCALMAN); then $(MKDIR) $(LOCALMAN); chmod 755 $(LOCALMAN); fi + @for i in 1 4 5 8; do for j in *.$$i; do if test ! -d $(LOCALMAN)/man$$i; then $(MKDIR) $(LOCALMAN)/man$$i; chmod 755 $(LOCALMAN)/man$$i; fi; cp $$j $(LOCALMAN)/man$$i/$$j; $(CHOWN) $(OWNER) $(LOCALMAN)/man$$i/$$j; chgrp $(GROUP) $(LOCALMAN)/man$$i/$$j; chmod 644 $(LOCALMAN)/man$$i/$$j; done; done + @echo "REMEMBER to run opiepasswd on your users immediately." + +install: client-install server-install + +uninstall: + @echo "Un-installing OPIE..." + @echo "Removing symlinks" + @-for i in otp-md4 otp-md5; do rm $(LOCALBIN)/$$i; done + @echo "Removing OPIE programs" + @-for i in opiekey opiepasswd opieinfo; do rm $(LOCALBIN)/$$i; done + @echo "Removing OPIE manual pages" + @-for i in 1 4 5 8; do for j in *.$$i; do rm $(LOCALMAN)/man$$i/$$j; done; done + @-rm $(LOCALMAN)/man1/otp-md4.1 $(LOCALMAN)/man1/otp-md5.1 + @echo "Restoring old binaries" + @-for i in $(SU) $(ALT_SU) $(LOGIN) $(FTPD); do FILE=`basename $$i`; if test ! $(EXISTS) $$i.$(BACKUP); then echo "No $$i.$(BACKUP)! Aborting."; exit 1; else echo "Removing $$FILE"; rm $$i || true; echo "Restoring old $$FILE"; mv $$i.$(BACKUP) $$i; fi; done + @echo "Resetting permissions" + @chmod 4111 $(SU) $(LOGIN) + @chmod 0100 $(FTPD) + @if test ! -z "$(ALT_SU)"; then chmod 4111 $(ALT_SU); fi + @echo "OPIE is now un-installed." + @echo "Please verify by hand that this process worked." + +opietest-passed: opietest + -./opietest && touch opietest-passed + +libopie/libopie.a: libopie/*.c *.h + (cd libopie ; $(MAKE) libopie.a CFL='$(CFLAGS) -DSTD_KEY_FILE=\"$(STD_KEY_FILE)\" -DEXT_KEY_FILE=\"$(EXT_KEY_FILE)\"') + +libmissing/libmissing.a: libmissing/*.c + (cd libmissing ; $(MAKE) libmissing.a CFL='$(CFLAGS)') + +clean: + -rm -f *.o opiekey opiegen opielogin opiepasswd opiesu opieftpd + -rm -f opieserv opieinfo opietest *core* opietest-passed + -rm -f Makefile.munge configure.munger y.tab.c .gdb* + (cd libopie ; $(MAKE) clean) + (cd libmissing ; $(MAKE) clean) + +realclean: clean + -rm -f *~ core* "\#*\#" Makefile make.log + -rm -f config.log config.status config.cache config.h + (cd libopie ; $(MAKE) realclean) + (cd libmissing ; $(MAKE) realclean) + +opiekey: opiekey.o $(LDEPS) + $(CC) $(CFLAGS) opiekey.o $(LFLAGS) -o opiekey + +opiegen: opiegen.o $(LDEPS) + $(CC) $(CFLAGS) opiegen.o $(LFLAGS) -o opiegen + +opieserv: opieserv.o $(LDEPS) + $(CC) $(CFLAGS) opieserv.o $(LFLAGS) -o opieserv + +opieftpd: opieftpd.o glob.o logwtmp.o popen.o y.tab.o $(LDEPS) + $(CC) $(CFLAGS) opieftpd.o glob.o logwtmp.o popen.o y.tab.o $(LFLAGS) -o opieftpd + +opielogin: opielogin.o permsfile.o $(LDEPS) + $(CC) $(CFLAGS) opielogin.o permsfile.o $(LFLAGS) -o opielogin + +opiepasswd: opiepasswd.o $(LDEPS) + $(CC) $(CFLAGS) opiepasswd.o $(LFLAGS) -o opiepasswd + +opiesu: opiesu.o $(LDEPS) + $(CC) $(CFLAGS) opiesu.o $(LFLAGS) -o opiesu + +y.tab.c: ftpcmd.y + $(YACC) ftpcmd.y + +opieinfo: opieinfo.o $(LDEPS) + $(CC) $(CFLAGS) opieinfo.o $(LFLAGS) -o opieinfo + +opietest: opietest.o $(LDEPS) + $(CC) $(CFLAGS) opietest.o $(LFLAGS) -o opietest diff --git a/contrib/opie/README b/contrib/opie/README new file mode 100644 index 0000000..63b4d8c --- /dev/null +++ b/contrib/opie/README @@ -0,0 +1,391 @@ +OPIE Software Distribution, Release 2.3 Important Information +======================================= ===================== + +Introduction +============ + + "One-time Passwords In Everything" (OPIE) is a freely distributable +software package originally developed at and for the US Naval Research +Laboratory (NRL). Recent versions are the result of a cooperative effort +between of NRL, several of the original NRL authors, The Inner Net, and many +other contributors from the Internet community. + + OPIE is an implementation of the One-Time Password (OTP) System that +is being considered for the Internet standards-track. OPIE provides a one-time +password system. The system should be secure against the passive attacks +now commonplace on the Internet (see RFC 1704 for more details). The system +is vulnerable to active dictionary attacks, though these are not widespread +at present and can be detected through proper use of system audit +software. + + OPIE is primarily written for UNIX-like operating systems, but +we are working to make applicable portions portable to other operating systems. +The OPIE software is derived in part from and is fully interoperable with the +Bell Communications Research (Bellcore) S/Key Release 1 software. Because +Bellcore claims "S/Key" as a trademark for their software, NRL was forced to +use a different name (we picked "OPIE") for this software distribution. + + OPIE includes the following additions/modifications to the +original Bellcore S/Key(tm) Version 1 software: + +* Just about three command installation (unpack the software, run the + configure script, and run make install). While we still recommend that you + follow instructions and test things by hand, the more adventurous can + install OPIE quickly. + +* A modified BSD FTP daemon that does OTP. + +* A version of su that uses OTP by default. + +* MD5 support. MD5 is now the default algorithm, though MD4 is still supported + by changing a parameter in the Makefile. This change was made because MD5 is + widely believed to be cryptographically stronger than MD4 (see RFC 1321). + +* A more portable version of MD4 has been substituted for the original MD4. + This should solve the endian problems that were in S/Key. + +* Most of the system-dependencies have been moved to a new file "opie_cfg.h". + +* Configuration options have been moved to the Makefile. + +* Isolated system dependencies (e.g. BSDisms) with appropriate #ifdefs. + +* Revised the opiekey(1) program to simultaneously support MD4 and MD5, with + the default algorithm being tunable using the MDX symbol in the Makefile. + +* More operating systems are supported by recent versions of OPIE, but older + BSD systems that aren't close to being compliant with the POSIX standard are + no longer supported. + +* Transition mechanisms are optional to prevent potential back doors. + +* On systems using the /etc/opieaccess transition mechanism, users can choose + to require the use of OPIE to login to their accounts when it would + otherwise be optional. + +* Bug fixes + +* Cosmetic changes + +* Prompts (optionally) identify specifically what kind of entry (system + password, secret pass phrase, or OTP response) is allowed. + +* Changes to mostly conform with the draft Internet OTP standard. + +A Glance at What's New +====================== + + 2.3 September 22, 1996 + + Autoconf is now the only supported configuration method. + + Lots of internal functions got re-written in ways that will make some +planned future changes easier. + + OTP extended responses, such as automatic re-initialization. + + Support for a supplemental key file that stores information that was +not in the original /etc/skeykeys file. This allows OPIE to store extra data +needed for things like the OTP re-initialization extended response without +breaking interoperability with other S/Key derived programs. This file is +named "/etc/opiekeys.ext" by default. Unlike the standard key file, it MUST +NOT be world readable. + + OPIE should better support some of the native "features" of drain +bamaged OSs such as AIX, HP-UX, and Solaris. + + OPIE's utmp/wtmp handling has been completely re-written. This should +solve many of the utmp/wtmp problems people have been having. + + Lots of cleanups. + + Bug fixes. + + 2.22 May 3, 1996. + + More minor bug fixes. OPIE once again works on Solaris 2.x. + + 2.21 April 27, 1996. + + Minor bug fixes. + + 2.2 April 11, 1996. + + opiesubr.c, opiesubr2.c, and a few other functions moved into +a subdirectory and split into files with fine granularity. Ditto with +missing function replacements. This subdirectory structure changes a lot +of things around and more splitting like this should be expected in the +near future. + + Added opiegenerator() library function that should make it very easy +to create OTP clients using the OPIE library (this function is subject to +change: there are a few problems remaining to be solved). Just about re-write +opiegetpass() to use raw I/O and got most of the OPIE programs actually using +that function. Autoconf build fixes. Lots of bug fixes. Lots of portability +fixes. Function declarations should be ANSI style for ANSI compilers. Several +fixes to bring OPIE in line with the latest OTP spec. MJR DES key crunch +de-implemented. + + Added sample programs: opiegen (client) and opieserv (server). + + Probably broke non-autoconf support along the way :(. I've tried to +bring this back in sync, but it may still be broken. + + 2.11 December 27, 1995. + + Minor bug fixes. + + 2.10 December 26, 1995. + + Optional autoconf support. opieinfo is now a normal program. +Bugs fixed -- should work much better on SunOS, HP-UX, and AIX. + +System Requirements +=================== + + In order to build and run properly, OPIE requires: + + * A UNIX-like operating system + * An ANSI C compiler and run-time library + * POSIX.1- and X/Open XPG-compliance (including termios) + * The BSD sockets API + * Approximately five megabytes of free disk space + + In practice, we believe that many systems who are close to meeting +these requirements but aren't completely there (for example, SunOS with the +native compiler) will also work. Systems who aren't anywhere near close +(for example, DOS) are not likely to work without major adjustments to the +OPIE code. + +If OPIE Doesn't Work +==================== + + First and foremost, make sure you have the latest version of OPIE. The +latest version is available by anonymous FTP at: + + ftp://ftp.nrl.navy.mil/pub/security/opie + and + ftp://ftp.inner.net/pub/opie + + If you have installed the OPIE software (either through "make test" +in (7) above or "make install" in (14)), you can run "make uninstall" from the +OPIE software distribution directory. This should remove the OPIE software and +restore the original system programs, but it will not work properly (and can +even result in the total loss of the old system programs -- beware!) if the +installation procedure itself did not work properly. + + OPIE is NOT supported software. We don't promise to support you or +even to acknowledge your mail, but we are interested in bug reports and are +reasonable folks. We also have an interest in seeing OPIE work on as many +systems as we can. However, if your system doesn't meet the basic requirements +for OPIE, this will probably require an unreasonable amount of effort. + + The best bug reports include a diagnosis of the problem and a fix. +Your bug report can still be valuable if you can at least diagnose what the +problem is. If you just tell us "it doesn't work," then we won't be able to +do anything to help you. + + We've received a number of bug reports from people that look +interesting, only to find when we try to follow up on them that the user +either has an invalid return address or never bothered to respond to our +followup. Please make sure that bug reports you send us have an electronic +mail address that we can reply to somewhere in them (if necessary, just +put it in the message body). If we send you a response and you are unable +to invest the time to work with us to solve the problem, please tell us -- +few things are more irritating than when someone sends us information +about a bug that we'd like to fix and then is never heard from again. + + We try to respond to all properly submitted bug reports. Improperly +submitted bug reports will be responded to only if we have time left after +responding to properly submitted bug reports. We deliberately ignore bug +"reports" sent to mailing lists or USENET news groups instead of or before +our bug report address. At the least, the latter practice is lacking in +courtesy. + + The file BUG-REPORT contains our bug reporting form. Please use it +and follow the submission instructions in that file. We are going to switch +to machine-parsed bug report processing sometime in the near future to make +it easier to coordinate bug hunting. + +Gotchas +======= + + While an almost universal "feature", most people remain unaware that +an intruder can log into a system, then log in again by running the "login" +command from a shell. Because the second login is from the local host, the +utmp entry will not show a remote login host anymore. The OPIE replacement +for /bin/login currently carries on this behavior for compatibility reasons. +If you would like to prevent this from happening, you should change the +permissions of /bin/login to 0100, thus preventing unprivileged users from +executing it. This fix should work on non-OPIE /bin/login programs as well. + + On 4.3BSDish systems, the supplied /bin/login replacement obtains +the terminal type for the console comes from the console line in the /etc/ttys +file. Several systems contain a default entry in this file that specifies the +console terminal type as "unknown". This is probably not what you want. + + The OPIE FTP daemon responds with two 530 error messages if you have +not yet logged in and execute a command that will also do a PORT request. This +is a feature, not a bug, as the FTP client is really sending the server two +commands (for instance, a PORT and a LIST if you tell your BSD FTP client to do +a DIR command) and the server is responding to each of them with an error. The +stock BSD FTP daemon doesn't check the PORT commands to see if you are logged +in, so you would only get one error message. This change should not break any +standards-compliant FTP client, but there are a number of brain-damaged GUI +clients that have a track record for not dealing gracefully with any server +other than the stock BSD one. + + The /etc/opieaccess transition mechanism is, by definition, a security +hole in the OPIE software because an attacker could use it to circumvent the +requirement for OPIE authentication. You should compile the software with +support for this file disabled unless you absolutely cannot use the software +without it because of your environment. If you do use this support for +transition purposes, you should move people to OTP authentication as quickly +as possible and rebuild and reinstall OPIE with this transition support +disabled so that you won't have a lurking security hole. + + If this wasn't already clear, do not let your sequence number fall +below about ten. If your sequence number reaches zero, your OTP sequence +can only be reset by the superuser. System administrators should make this +caveat known to their users. + + On Solaris 2.x systems (and possibly others) running NIS+, users +should run keylogin(1) manually after login because opielogin(1) does not +do that automatically like the system login(1) program. + + There are reports that some versions of GNU C Compiler (GCC) +(when installed on some systems) use their own termios(4) instead of +the system's termios(4). This can cause problems. If you are having +compilation problems that seem to relate to termios and you are using +GCC, you should probably verify that it is using the system's +termios(4) and not some internal-to-GCC termios(4). One report +indicates that Sun's C compiler works fine with SunOS 4.1.3/4.1.4 on +SPARC, but that some version of GCC on the same system has this +termios(4) problem. We haven't reproduced these problems ourselves +and hence aren't sure what is happening, but we pass this along for +your information. (This may have something to do with the use of GNU +libc) + + If a user has a valid entry in the opiekeys database but has an +asterisk in their traditional password entry, they will not be able to +log in via opielogin, but opielogin will decrement their sequence number +if a valid response is received. + + On some systems, the OPIE login program does not always display +a "login:" prompt the first time. We think that this has something to do +with the telnet daemon on those systems. (This is common on SunOS) You should +be able to fix this by upgrading to the latest version of telnetd. + + The standard HPUX compiler is severely drain bamaged. One of the +worst parts is that it sometimes won't grok a symbol definition with forward +slashes in them properly and can choke badly on the definition of the key +file's location. If this happens to you, install and use GCC. (This problem +may or may not also come up with the optional HP ANSI C compiler -- we don't +know for sure what compilers have this problem). + + As of OPIE 2.2, the seed is converted to lower case and its length is +checked in order to comply with the OTP specification. If any of your users +have seeds that use capital letters or are too long, they need to run the OPIE +2.2 opiepasswd program to re-initialize their sequence to one with a different +seed. + + opielogin is a replacement for /bin/login. It is NOT an OPIE "shell." +You can use it as one, but don't be surprised if it doesn't behave the way +you expect. An OPIE "shell" is on the TODO list. + + Clients that use opiegen() will automatically send a re-initialization +extended response if the sequence number falls below ten. If the server does +not support this, the user will need to log in using opiekey and reset his +sequence manually (using opiepasswd). + +Gripes +====== + + Is it too much to ask that certain OS vendors just do the right thing +and not fix what isn't broken? (Look at all the ifdefs in the OPIE code and +the answer is clear) + +Credits +======= + + First and foremost credit goes to Phil Karn, Neil M. Haller, and John +S. Walden of Bellcore for creating the S/Key Version 1 software distribution +and for making its source code freely available to the public. Without their +work, OPIE would not exist. Neil has also invested a good amount of his time +in the development of a standard for One-Time Passwords so that packages like +OPIE can interoperate. + + The first NRL OPIE distribution included modifications made primarily +by Dan McDonald of the U.S. Naval Research Laboratory (NRL) during March 1994. +The 2nd NRL OPIE distribution, which has a number of improvements in areas +such as portability of software and ease of installation, is primarily the +work of Ran Atkinson and Craig Metz. Other NRL contributors include Brian +Adamson, Steve Batsell, Preston Mullen, Bao Phan, Jim Ramsey, and Georg Thomas. + + Some of version 2.2 was developed at NRL and released as a work in +progress. Most of the release version was developed by Craig Metz (also of +NRL), others at The Inner Net, and contributors from the Internet community. +Versions beyond 2.2 were developed outside NRL, so don't blame them if they +don't work (But please credit them when it does. Without the NRL effort, there +wouldn't be an OPIE). + + We would like to also thank everyone who helped us by by beta testing, +reporting bugs, suggesting improvements, and/or sending us patches. We +appreciate your contributions -- they have helped to make OPIE more of a +community effort. These contributors include: + + Mowgli Assor + Lawrie Brown + Axel Grewe + "Hobbit" + Darren Hosking + Martijn Koster + Osamu Kurati + Ayamura Kikuchi + Ikuo Nakagawa + Angelo Neri + D. Jason Penney + John Perkins + Jim Simmons + Werner Wiethege + Wietse Venema + + OPIE development at NRL was sponsored by the Information Security +Program Office (PD 71E), U.S. Space and Naval Warfare Systems Command, Crystal +City, Virginia. + + If you have problems with OPIE, please follow the instructions under +"If OPIE Doesn't Work." Under NO circumstances should you send trouble +reports directly to the authors or contributors. + +Trademarks +========== +S/Key is a trademark of Bell Communications Research (Bellcore). +UNIX is a trademark of X/Open. +NRL is a trademark of the U. S. Naval Research Laboratory. + +All other trademarks are trademarks of their respective owners. + +The term "OPIE" is in the public domain and hence cannot be legally +trademarked by anyone. + +Copyrights +========== +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + +Portions of this software are copyright 1980-1990 Regents of the +University of California, all rights reserved. The Berkeley Software +License Agreement specifies the terms and conditions for redistribution. + +Portions of this software are copyright 1990 Bell Communications Research +(Bellcore), all rights reserved. diff --git a/contrib/opie/acconfig.h b/contrib/opie/acconfig.h new file mode 100644 index 0000000..27a45c4 --- /dev/null +++ b/contrib/opie/acconfig.h @@ -0,0 +1,118 @@ +/* acconfig.h: Extra commentary for Autoheader + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +/* Define if the closedir function returns void instead of int. */ +#undef CLOSEDIR_VOID + +/* Define if you want the FTP daemon to support anonymous logins. */ +#undef DOANONYMOUS + +/* The default value of the PATH environment variable */ +#undef DEFAULT_PATH + +/* Defined if the file /etc/default/login exists + (and, presumably, should be looked at by login) */ +#undef HAVE_ETC_DEFAULT_LOGIN + +/* Defined to the name of a file that contains a list of files whose + permissions and ownerships should be changed on login. */ +#undef HAVE_LOGIN_PERMFILE + +/* Defined to the name of a file that contains a list of environment + values that should be set on login. */ +#undef HAVE_LOGIN_ENVFILE + +/* Defined if the file /etc/securetty exists + (and, presumably, should be looked at by login) */ +#undef HAVE_SECURETTY + +/* Defined if the file /etc/shadow exists + (and, presumably, should be looked at for shadow passwords) */ +#undef HAVE_ETC_SHADOW + +/* The path to the access file, if we're going to use it */ +#undef PATH_ACCESS_FILE + +/* The path to the mail spool, if we know it */ +#undef PATH_MAIL + +/* The path to the utmp file, if we know it */ +#undef PATH_UTMP_AC + +/* The path to the utmpx file, if we know it */ +#undef PATH_UTMPX_AC + +/* The path to the wtmp file, if we know it */ +#undef PATH_WTMP_AC + +/* The path to the wtmpx file, if we know it */ +#undef PATH_WTMPX_AC + +/* Defined if the system's profile (/etc/profile) displays + the motd file */ +#undef HAVE_MOTD_IN_PROFILE + +/* Defined if the system's profile (/etc/profile) informs the + user of new mail */ +#undef HAVE_MAILCHECK_IN_PROFILE + +/* Define if you have a nonstandard gettimeofday() that takes one argument + instead of two. */ +#undef HAVE_ONE_ARG_GETTIMEOFDAY + +/* Define if the system has the getenv function */ +#undef HAVE_GETENV + +/* Define if the system has the setenv function */ +#undef HAVE_SETENV + +/* Define if the system has the /var/adm/sulog file */ +#undef HAVE_SULOG + +/* Define if the system has the unsetenv function */ +#undef HAVE_UNSETENV + +/* Define if the compiler can handle ANSI-style argument lists */ +#undef HAVE_ANSIDECL + +/* Define if the compiler can handle ANSI-style prototypes */ +#undef HAVE_ANSIPROTO + +/* Define if the system has an ANSI-style printf (returns int instead of char *) */ +#undef HAVE_ANSISPRINTF + +/* Define if the compiler can handle ANSI-style variable argument lists */ +#undef HAVE_ANSISTDARG + +/* Define if the compiler can handle void argument lists to functions */ +#undef HAVE_VOIDARG + +/* Define if the compiler can handle void return "values" from functions */ +#undef HAVE_VOIDRET + +/* Define if the compiler can handle void pointers to our liking */ +#undef HAVE_VOIDPTR + +/* Define if the /bin/ls command seems to support the -g flag */ +#undef HAVE_LS_G_FLAG + +/* Define if there is a ut_pid field in struct utmp */ +#undef HAVE_UT_PID + +/* Define if there is a ut_type field in struct utmp */ +#undef HAVE_UT_TYPE + +/* Define if there is a ut_user field in struct utmp */ +#undef HAVE_UT_USER + +/* Define if there is a ut_name field in struct utmp */ +#undef HAVE_UT_NAME + +/* Define if there is a ut_host field in struct utmp */ +#undef HAVE_UT_HOST diff --git a/contrib/opie/config.h.in b/contrib/opie/config.h.in new file mode 100644 index 0000000..1fdbff9 --- /dev/null +++ b/contrib/opie/config.h.in @@ -0,0 +1,324 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* 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 using alloca.c. */ +#undef C_ALLOCA + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define if on MINIX. */ +#undef _MINIX + +/* Define if the system does not provide POSIX.1 features except + with this defined. */ +#undef _POSIX_1_SOURCE + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Define as the return type of signal handlers (int or void). */ +#undef RETSIGTYPE + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if you want the FTP daemon to support anonymous logins. */ +#undef DOANONYMOUS + +/* The default value of the PATH environment variable */ +#undef DEFAULT_PATH + +/* Defined if the file /etc/default/login exists + (and, presumably, should be looked at by login) */ +#undef HAVE_ETC_DEFAULT_LOGIN + +/* Defined to the name of a file that contains a list of files whose + permissions and ownerships should be changed on login. */ +#undef HAVE_LOGIN_PERMFILE + +/* Defined to the name of a file that contains a list of environment + values that should be set on login. */ +#undef HAVE_LOGIN_ENVFILE + +/* Defined if the file /etc/securetty exists + (and, presumably, should be looked at by login) */ +#undef HAVE_SECURETTY + +/* Defined if the file /etc/shadow exists + (and, presumably, should be looked at for shadow passwords) */ +#undef HAVE_ETC_SHADOW + +/* The path to the access file, if we're going to use it */ +#undef PATH_ACCESS_FILE + +/* The path to the mail spool, if we know it */ +#undef PATH_MAIL + +/* Defined if the system's profile (/etc/profile) displays + the motd file */ +#undef HAVE_MOTD_IN_PROFILE + +/* Defined if the system's profile (/etc/profile) informs the + user of new mail */ +#undef HAVE_MAILCHECK_IN_PROFILE + +/* Define if you have a nonstandard gettimeofday() that takes one argument + instead of two. */ +#undef HAVE_ONE_ARG_GETTIMEOFDAY + +/* Define if the system has the getenv function */ +#undef HAVE_GETENV + +/* Define if the system has the setenv function */ +#undef HAVE_SETENV + +/* Define if the system has the /var/adm/sulog file */ +#undef HAVE_SULOG + +/* Define if the system has the unsetenv function */ +#undef HAVE_UNSETENV + +/* Define if the compiler can handle ANSI-style argument lists */ +#undef HAVE_ANSIDECL + +/* Define if the compiler can handle ANSI-style prototypes */ +#undef HAVE_ANSIPROTO + +/* Define if the system has an ANSI-style printf (returns int instead of char *) */ +#undef HAVE_ANSISPRINTF + +/* Define if the compiler can handle ANSI-style variable argument lists */ +#undef HAVE_ANSISTDARG + +/* Define if the compiler can handle void argument lists to functions */ +#undef HAVE_VOIDARG + +/* Define if the compiler can handle void return "values" from functions */ +#undef HAVE_VOIDRET + +/* Define if the compiler can handle void pointers to our liking */ +#undef HAVE_VOIDPTR + +/* Define if the /bin/ls command seems to support the -g flag */ +#undef HAVE_LS_G_FLAG + +/* Define if there is a ut_pid field in struct utmp */ +#undef HAVE_UT_PID + +/* Define if there is a ut_type field in struct utmp */ +#undef HAVE_UT_TYPE + +/* Define if there is a ut_name field in struct utmp */ +#undef HAVE_UT_NAME + +/* Define if there is a ut_host field in struct utmp */ +#undef HAVE_UT_HOST + +/* Define if you have the bcopy function. */ +#undef HAVE_BCOPY + +/* Define if you have the bzero function. */ +#undef HAVE_BZERO + +/* Define if you have the endspent function. */ +#undef HAVE_ENDSPENT + +/* Define if you have the fpurge function. */ +#undef HAVE_FPURGE + +/* Define if you have the getdtablesize function. */ +#undef HAVE_GETDTABLESIZE + +/* Define if you have the getgroups function. */ +#undef HAVE_GETGROUPS + +/* Define if you have the gethostname function. */ +#undef HAVE_GETHOSTNAME + +/* Define if you have the getspent function. */ +#undef HAVE_GETSPENT + +/* Define if you have the gettimeofday function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define if you have the getttynam function. */ +#undef HAVE_GETTTYNAM + +/* Define if you have the getutxline function. */ +#undef HAVE_GETUTXLINE + +/* Define if you have the getwd function. */ +#undef HAVE_GETWD + +/* Define if you have the index function. */ +#undef HAVE_INDEX + +/* Define if you have the lstat function. */ +#undef HAVE_LSTAT + +/* Define if you have the pututxline function. */ +#undef HAVE_PUTUTXLINE + +/* Define if you have the rindex function. */ +#undef HAVE_RINDEX + +/* Define if you have the setegid function. */ +#undef HAVE_SETEGID + +/* Define if you have the seteuid function. */ +#undef HAVE_SETEUID + +/* Define if you have the setgroups function. */ +#undef HAVE_SETGROUPS + +/* Define if you have the setlogin function. */ +#undef HAVE_SETLOGIN + +/* Define if you have the setpriority function. */ +#undef HAVE_SETPRIORITY + +/* Define if you have the setregid function. */ +#undef HAVE_SETREGID + +/* Define if you have the setresgid function. */ +#undef HAVE_SETRESGID + +/* Define if you have the setresuid function. */ +#undef HAVE_SETRESUID + +/* Define if you have the setreuid function. */ +#undef HAVE_SETREUID + +/* Define if you have the setvbuf function. */ +#undef HAVE_SETVBUF + +/* Define if you have the sigblock function. */ +#undef HAVE_SIGBLOCK + +/* Define if you have the sigsetmask function. */ +#undef HAVE_SIGSETMASK + +/* Define if you have the socket function. */ +#undef HAVE_SOCKET + +/* Define if you have the strftime function. */ +#undef HAVE_STRFTIME + +/* Define if you have the strstr function. */ +#undef HAVE_STRSTR + +/* Define if you have the sysconf function. */ +#undef HAVE_SYSCONF + +/* Define if you have the ttyslot function. */ +#undef HAVE_TTYSLOT + +/* Define if you have the header file. */ +#undef HAVE_CRYPT_H + +/* Define if you have the header file. */ +#undef HAVE_DIRENT_H + +/* Define if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_LASTLOG_H + +/* Define if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the header file. */ +#undef HAVE_NDIR_H + +/* Define if you have the header file. */ +#undef HAVE_PATHS_H + +/* Define if you have the header file. */ +#undef HAVE_PWD_H + +/* Define if you have the header file. */ +#undef HAVE_SHADOW_H + +/* Define if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_DIR_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_NDIR_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SIGNAL_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_UTSNAME_H + +/* Define if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_UTMPX_H + +/* Define if you have the crypt library (-lcrypt). */ +#undef HAVE_LIBCRYPT + +/* Define if you have the nsl library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define if you have the posix library (-lposix). */ +#undef HAVE_LIBPOSIX + +/* Define if you have the socket library (-lsocket). */ +#undef HAVE_LIBSOCKET diff --git a/contrib/opie/config.testeflag b/contrib/opie/config.testeflag new file mode 100644 index 0000000..cc16df4 --- /dev/null +++ b/contrib/opie/config.testeflag @@ -0,0 +1,12 @@ +#! /bin/sh +if test -e README >/dev/null 2>/dev/null +then + if test -e a.non-existant-file >/dev/null 2>/dev/null + then + exit 1 + else + exit 0 + fi +else + exit 1 +fi diff --git a/contrib/opie/configure b/contrib/opie/configure new file mode 100755 index 0000000..f635e08 --- /dev/null +++ b/contrib/opie/configure @@ -0,0 +1,4089 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.10 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-access-file=PATH Use the OPIE access file PATH as a transition aid" +ac_help="$ac_help + --enable-anonymous-ftp Enable anonymous FTP support" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.10" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=README + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +# Check whether --enable-access-file or --disable-access-file was given. +if test "${enable_access_file+set}" = set; then + enableval="$enable_access_file" + cat >> confdefs.h <> confdefs.h <<\EOF +#define DOANONYMOUS 1 +EOF + echo "Enabling anonymous FTP support in ftp -- don't say we didn't warn you!" +fi + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 +if test $ac_cv_prog_gcc = yes; then + GCC=yes + if test "${CFLAGS+set}" != set; then + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_gcc_g=yes +else + ac_cv_prog_gcc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6 + if test $ac_cv_prog_gcc_g = yes; then + CFLAGS="-g -O" + else + CFLAGS="-O" + fi + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:684: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:699: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi +fi +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +for ac_prog in 'bison -y' byacc +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_YACC="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +YACC="$ac_cv_prog_YACC" +if test -n "$YACC"; then + echo "$ac_t""$YACC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + + +echo $ac_n "checking for AIX""... $ac_c" 1>&6 +cat > conftest.$ac_ext <&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF +#define _ALL_SOURCE 1 +EOF + +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + + +echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 +then + echo "$ac_t""yes" 1>&6 + ISC=yes # If later tests want to check for ISC. + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +else + echo "$ac_t""no" 1>&6 + ISC= +fi + +ac_safe=`echo "minix/config.h" | tr './\055' '___'` +echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:855: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + MINIX=yes +else + echo "$ac_t""no" 1>&6 +MINIX= +fi + +if test "$MINIX" = yes; then + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + cat >> confdefs.h <<\EOF +#define _POSIX_1_SOURCE 2 +EOF + + cat >> confdefs.h <<\EOF +#define _MINIX 1 +EOF + +fi + + +# If we cannot run a trivial program, we must be cross compiling. +echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_cross=yes +else +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } +if test -s conftest && (./conftest; exit) 2>/dev/null; then + ac_cv_c_cross=no +else + ac_cv_c_cross=yes +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ac_cv_c_cross" 1>&6 +cross_compiling=$ac_cv_c_cross + + + +# Extract the first word of "chown", so it can be a program name with args. +set dummy chown; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_path_CHOWN'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$CHOWN" in + /*) + ac_cv_path_CHOWN="$CHOWN" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/bin /bin /usr/sbin /sbin /usr/etc /etc; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_CHOWN="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_CHOWN" && ac_cv_path_CHOWN="/bin/chown" + ;; +esac +fi +CHOWN="$ac_cv_path_CHOWN" +if test -n "$CHOWN"; then + echo "$ac_t""$CHOWN" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +# Extract the first word of "su", so it can be a program name with args. +set dummy su; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_path_SU'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$SU" in + /*) + ac_cv_path_SU="$SU" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/bin /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_SU="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_SU" && ac_cv_path_SU="/bin/su" + ;; +esac +fi +SU="$ac_cv_path_SU" +if test -n "$SU"; then + echo "$ac_t""$SU" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "su", so it can be a program name with args. +set dummy su; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_path_ALT_SU'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$ALT_SU" in + /*) + ac_cv_path_ALT_SU="$ALT_SU" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/sbin /sbin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_ALT_SU="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +ALT_SU="$ac_cv_path_ALT_SU" +if test -n "$ALT_SU"; then + echo "$ac_t""$ALT_SU" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +# Extract the first word of "scheme", so it can be a program name with args. +set dummy scheme; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_path_SCHEME'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$SCHEME" in + /*) + ac_cv_path_SCHEME="$SCHEME" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/lib/iaf/scheme; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_SCHEME="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +SCHEME="$ac_cv_path_SCHEME" +if test -n "$SCHEME"; then + echo "$ac_t""$SCHEME" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "login", so it can be a program name with args. +set dummy login; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_path_LOGIN'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$LOGIN" in + /*) + ac_cv_path_LOGIN="$LOGIN" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/bin /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_LOGIN="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_LOGIN" && ac_cv_path_LOGIN="/bin/login" + ;; +esac +fi +LOGIN="$ac_cv_path_LOGIN" +if test -n "$LOGIN"; then + echo "$ac_t""$LOGIN" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +if test ! -z "$SCHEME"; +then + LOGIN="$SCHEME"; +fi + +# Extract the first word of "ftpd", so it can be a program name with args. +set dummy ftpd; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_path_FTPD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$FTPD" in + /*) + ac_cv_path_FTPD="$FTPD" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/libexec /usr/etc /etc /usr/sbin /sbin /usr/lbin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_FTPD="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +FTPD="$ac_cv_path_FTPD" +if test -n "$FTPD"; then + echo "$ac_t""$FTPD" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Extract the first word of "in.ftpd", so it can be a program name with args. +set dummy in.ftpd; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_path_INFTPD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$INFTPD" in + /*) + ac_cv_path_INFTPD="$INFTPD" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/libexec /usr/etc /etc /usr/sbin /sbin /usr/lbin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_INFTPD="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +INFTPD="$ac_cv_path_INFTPD" +if test -n "$INFTPD"; then + echo "$ac_t""$INFTPD" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + +if test -z "$FTPD" +then + if test ! -z "$INFTPD" + then + FTPD="$INFTPD" + fi +fi + +echo $ac_n "checking for default PATH entries""... $ac_c" 1>&6 +default_path="" +save_IFS="$IFS" +IFS=" " +for i in /usr/bin /bin /usr/ucb /usr/sbin /usr/bsd /sbin /usr/bin/X11 /etc /usr/local/X11/bin /usr/X11R6/bin /your-system-is-broken +do + IFS=":" + for j in $PATH + do + if test "$i" = "$j" + then + if test -d "$i" + then + if test -z "$default_path" + then + default_path="$i" + else + default_path="$default_path:$i" + fi + fi + fi + done + IFS=" " +done +cat >> confdefs.h <&6 + +echo $ac_n "checking for test -e flag""... $ac_c" 1>&6 +if sh config.testeflag +then + result=yes + EXISTS="-e" +else + result=no + EXISTS="-f" +fi + +echo "$ac_t""$result" 1>&6 + +echo $ac_n "checking for mkdir -p flag""... $ac_c" 1>&6 +if test -d config.tmpdir +then + rmdir config.tmpdir/foo/bar >/dev/null 2>/dev/null + rmdir config.tmpdir/foo >/dev/null 2>/dev/null + rmdir config.tmpdir >/dev/null 2>/dev/null +fi + +result=no +if mkdir -p config.tmpdir/foo/bar >/dev/null 2>/dev/null +then + if test -d config.tmpdir + then + if test -d config.tmpdir/foo + then + if test -d config.tmpdir/foo/bar + then + result=yes + rmdir config.tmpdir/foo/bar >/dev/null 2>/dev/null + fi + rmdir config.tmpdir/foo >/dev/null 2>/dev/null + fi + rmdir config.tmpdir >/dev/null 2>/dev/null + fi +fi + +if test "$result" = yes +then + MKDIR="mkdir -p" +else + MKDIR="mkdir" +fi + +echo "$ac_t""$result" 1>&6 + +echo $ac_n "checking for ls group field""... $ac_c" 1>&6 +lsg=`/bin/ls -ldg / | wc -w | awk '{print $1}'`; +ls=`/bin/ls -ld / | wc -w | awk '{print $1}'`; +result="no" +if test $ls = 9; +then + result="yes" +else + if test "$ls" = 8 -a "$lsg" = 9; + then + result="yes, with -g" + cat >> confdefs.h <<\EOF +#define HAVE_LS_G_FLAG 1 +EOF + + fi +fi +echo "$ac_t""$result" 1>&6 + +echo $ac_n "checking for /etc/default/login""... $ac_c" 1>&6 +if test $EXISTS /etc/default/login +then + result=yes + cat >> confdefs.h <<\EOF +#define HAVE_ETC_DEFAULT_LOGIN 1 +EOF + +else + result=no +fi +echo "$ac_t""$result" 1>&6 + +echo $ac_n "checking for /etc/securetty""... $ac_c" 1>&6 +if test $EXISTS /etc/securetty +then + result=yes + cat >> confdefs.h <<\EOF +#define HAVE_SECURETTY 1 +EOF + +else + result=no +fi +echo "$ac_t""$result" 1>&6 + +echo $ac_n "checking for /etc/logindevperm""... $ac_c" 1>&6 +if test $EXISTS /etc/logindevperm +then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_LOGIN_PERMFILE "/etc/logindevperm" +EOF + +else + echo "$ac_t""no" 1>&6 + + echo $ac_n "checking for /etc/fbtab""... $ac_c" 1>&6 + if test $EXISTS /etc/fbtab + then + result=yes + cat >> confdefs.h <<\EOF +#define HAVE_LOGIN_PERMFILE "/etc/fbtab" +EOF + + else + result=no + fi + echo "$ac_t""$result" 1>&6 +fi + +echo $ac_n "checking for /etc/environment""... $ac_c" 1>&6 +if test $EXISTS /etc/environment +then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_LOGIN_ENVFILE "/etc/environment" +EOF + +else + echo "$ac_t""no" 1>&6 + + echo $ac_n "checking for /etc/src.sh""... $ac_c" 1>&6 + if test $EXISTS /etc/src.sh + then + result=yes + cat >> confdefs.h <<\EOF +#define HAVE_LOGIN_ENVFILE "/etc/src.sh" +EOF + + else + result=no + fi + echo "$ac_t""$result" 1>&6 +fi + +echo $ac_n "checking for /etc/shadow""... $ac_c" 1>&6 +if test $EXISTS /etc/shadow +then + result=yes + cat >> confdefs.h <<\EOF +#define HAVE_ETC_SHADOW 1 +EOF + +else + result=no +fi +echo "$ac_t""$result" 1>&6 + +echo $ac_n "checking for /var/adm/sulog""... $ac_c" 1>&6 +if test $EXISTS /var/adm/sulog +then + result=yes + cat >> confdefs.h <<\EOF +#define HAVE_SULOG 1 +EOF + +else + result=no +fi +echo "$ac_t""$result" 1>&6 + +echo $ac_n "checking mail spool location""... $ac_c" 1>&6 +mail_spool="" +for i in /var/mail /usr/mail /var/spool/mail /usr/spool/mail +do + if test -d $i + then + mail_spool="$i" + fi +done +if test -z "$mail_spool" +then + result="not found" +else + result="$mail_spool" + cat >> confdefs.h <&6 + + + +echo $ac_n "checking whether the system profile displays the motd""... $ac_c" 1>&6 +result=no +if test $EXISTS /etc/profile +then + if grep motd /etc/profile >/dev/null 2>/dev/null + then + result=yes + fi +fi +if test "$result" = yes +then + cat >> confdefs.h <<\EOF +#define HAVE_MOTD_IN_PROFILE 1 +EOF + +fi +echo "$ac_t""$result" 1>&6 + +echo $ac_n "checking whether the system profile checks for mail""... $ac_c" 1>&6 +result=no +if test $EXISTS /etc/profile +then + if grep 'mail\.' /etc/profile >/dev/null 2>/dev/null + then + result=yes + fi +fi +if test "$result" = yes +then + cat >> confdefs.h <<\EOF +#define HAVE_MAILCHECK_IN_PROFILE 1 +EOF + +fi +echo "$ac_t""$result" 1>&6 + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:1461: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + + +echo $ac_n "checking to see if your compiler can handle void arguments""... $ac_c" 1>&6 +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_VOIDARG 1 +EOF + echo "$ac_t""yes" 1>&6 +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + + +echo $ac_n "checking to see if your compiler can handle void return values""... $ac_c" 1>&6 +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_VOIDRET 1 +EOF + echo "$ac_t""yes" 1>&6 +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + + +echo $ac_n "checking to see if your compiler can handle void pointers""... $ac_c" 1>&6 +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_VOIDPTR 1 +EOF + echo "$ac_t""yes" 1>&6 +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + + +echo $ac_n "checking to see if your compiler can handle ANSI argument lists""... $ac_c" 1>&6 +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_ANSIDECL 1 +EOF + echo "$ac_t""yes" 1>&6 +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + + +echo $ac_n "checking to see if your compiler can handle ANSI prototypes""... $ac_c" 1>&6 +cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_ANSIPROTO 1 +EOF + echo "$ac_t""yes" 1>&6 +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + + +echo $ac_n "checking to see if your compiler can handle ANSI variable arguments""... $ac_c" 1>&6 +cat > conftest.$ac_ext < +int foo(int arg, ...) { + va_list ap; + va_start(ap, arg); + va_end(ap); + return 0; +} +int main() { return 0; } +int t() { + +; return 0; } +EOF +if { (eval echo configure:1612: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_ANSISTDARG 1 +EOF + echo "$ac_t""yes" 1>&6 +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + + +echo $ac_n "checking to see if you have an ANSI-style sprintf""... $ac_c" 1>&6 +if test "$cross_compiling" = yes; then + echo "$ac_t""no" 1>&6 +else +cat > conftest.$ac_ext < +int main(argc, argv) +int argc; +char *argv[]; +{ + char buf[5]; + int i = 2; + i += sprintf(buf, "1234"); + return (i == 6) ? 0 : -1; +} +EOF +{ (eval echo configure:1643: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } +if test -s conftest && (./conftest; exit) 2>/dev/null; then + cat >> confdefs.h <<\EOF +#define HAVE_ANSISPRINTF 1 +EOF + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi +fi +rm -fr conftest* + +echo $ac_n "checking for -lcrypt""... $ac_c" 1>&6 +ac_lib_var=`echo crypt'_'crypt | tr './+\055' '__p_'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lcrypt $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo crypt | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi + +echo $ac_n "checking for -lnsl""... $ac_c" 1>&6 +ac_lib_var=`echo nsl'_'gethostname | tr './+\055' '__p_'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo nsl | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi + +echo $ac_n "checking for -lposix""... $ac_c" 1>&6 +ac_lib_var=`echo posix'_'main | tr './+\055' '__p_'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lposix $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo posix | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi + +echo $ac_n "checking for -lsocket""... $ac_c" 1>&6 +ac_lib_var=`echo socket'_'socket | tr './+\055' '__p_'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo socket | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h +do +ac_safe=`echo "$ac_hdr" | tr './\055' '___'` +echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include <$ac_hdr> +int main() { return 0; } +int t() { +DIR *dirp = 0; +; return 0; } +EOF +if { (eval echo configure:1846: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=yes" +else + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdedfghijklmnopqrstuvwxyz./\055' 'ABCDEDFGHIJKLMNOPQRSTUVWXYZ___'` + cat >> confdefs.h <&6 +fi +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then +echo $ac_n "checking for -ldir""... $ac_c" 1>&6 +ac_lib_var=`echo dir'_'opendir | tr './+\055' '__p_'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldir $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -ldir" +else + echo "$ac_t""no" 1>&6 +fi + +else +echo $ac_n "checking for -lx""... $ac_c" 1>&6 +ac_lib_var=`echo x'_'opendir | tr './+\055' '__p_'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lx $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -lx" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif +int main() { return 0; } +int t() { +int s; +wait (&s); +s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; +; return 0; } +EOF +if { (eval echo configure:1970: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_sys_wait_h=yes +else + rm -rf conftest* + ac_cv_header_sys_wait_h=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6 +if test $ac_cv_header_sys_wait_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_SYS_WAIT_H 1 +EOF + +fi + +for ac_hdr in crypt.h fcntl.h limits.h termios.h sys/file.h sys/ioctl.h sys/time.h syslog.h unistd.h paths.h shadow.h signal.h sys/signal.h lastlog.h sys/utsname.h pwd.h sys/param.h string.h stdlib.h utmpx.h +do +ac_safe=`echo "$ac_hdr" | tr './\055' '___'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2002: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdefghijklmnopqrstuvwxyz./\055' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ___'` + cat >> confdefs.h <&6 +fi +done + + + +echo $ac_n "checking for ut_pid in struct utmp""... $ac_c" 1>&6 +cat > conftest.$ac_ext < +#include +int main() { return 0; } +int t() { +struct utmp foo; return (int)foo.ut_pid; +; return 0; } +EOF +if { (eval echo configure:2039: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_UT_PID 1 +EOF + echo "$ac_t""yes" 1>&6 +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + +echo $ac_n "checking for ut_type in struct utmp""... $ac_c" 1>&6 +cat > conftest.$ac_ext < +#include +int main() { return 0; } +int t() { +struct utmp foo; return (int)foo.ut_type; +; return 0; } +EOF +if { (eval echo configure:2062: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_UT_TYPE 1 +EOF + echo "$ac_t""yes" 1>&6 +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + +echo $ac_n "checking for ut_name in struct utmp""... $ac_c" 1>&6 +cat > conftest.$ac_ext < +#include +int main() { return 0; } +int t() { +struct utmp foo; return (int)foo.ut_name[0]; +; return 0; } +EOF +if { (eval echo configure:2085: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_UT_NAME 1 +EOF + echo "$ac_t""yes" 1>&6 +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + +cat >> confdefs.h <<\EOF +#define HAVE_UT_HOST 1 +EOF + + +echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifdef signal +#undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif + +int main() { return 0; } +int t() { +int i; +; return 0; } +EOF +if { (eval echo configure:2125: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_type_signal=void +else + rm -rf conftest* + ac_cv_type_signal=int +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_type_signal" 1>&6 +cat >> confdefs.h <&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2173: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_memcmp'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_memcmp=no +else +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } +if test -s conftest && (./conftest; exit) 2>/dev/null; then + ac_cv_func_memcmp=yes +else + ac_cv_func_memcmp=no +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ac_cv_func_memcmp" 1>&6 +test $ac_cv_func_memcmp = no && LIBOBJS="$LIBOBJS memcmp.o" + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { return 0; } +int t() { +char *p = alloca(2 * sizeof(int)); +; return 0; } +EOF +if { (eval echo configure:2242: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + ac_cv_header_alloca_h=yes +else + rm -rf conftest* + ac_cv_header_alloca_h=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_header_alloca_h" 1>&6 +if test $ac_cv_header_alloca_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA_H 1 +EOF + +fi + +echo $ac_n "checking for alloca""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_alloca'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +#endif + +int main() { return 0; } +int t() { +char *p = (char *) alloca(1); +; return 0; } +EOF +if { (eval echo configure:2290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + ac_cv_func_alloca=yes +else + rm -rf conftest* + ac_cv_func_alloca=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_func_alloca" 1>&6 +if test $ac_cv_func_alloca = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA 1 +EOF + +fi + +if test $ac_cv_func_alloca = no; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.o + cat >> confdefs.h <<\EOF +#define C_ALLOCA 1 +EOF + + +echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5 | + egrep "webecray" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_os_cray=yes +else + rm -rf conftest* + ac_cv_os_cray=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_os_cray" 1>&6 +if test $ac_cv_os_cray = yes; then +for ac_func in _getb67 GETB67 getb67; do + echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2378: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <&6 +fi + +done +fi + +echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else +cat > conftest.$ac_ext < addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +} +EOF +{ (eval echo configure:2429: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } +if test -s conftest && (./conftest; exit) 2>/dev/null; then + ac_cv_c_stack_direction=1 +else + ac_cv_c_stack_direction=-1 +fi +fi +rm -fr conftest* +fi + +echo "$ac_t""$ac_cv_c_stack_direction" 1>&6 +cat >> confdefs.h <&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2477: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +LIBOBJS="$LIBOBJS ${ac_func}.o" +fi + +done + +MISSING="$LIBOBJS $ALLOCA " +echo $ac_n "checking for atexit""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_atexit'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char atexit(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_atexit) || defined (__stub___atexit) +choke me +#else +atexit(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_atexit=yes" +else + rm -rf conftest* + eval "ac_cv_func_atexit=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'atexit`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}atexit.o " +fi + +echo $ac_n "checking for entutent""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_entutent'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char entutent(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_entutent) || defined (__stub___entutent) +choke me +#else +entutent(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2574: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_entutent=yes" +else + rm -rf conftest* + eval "ac_cv_func_entutent=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'entutent`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}endutent.o " +fi + +echo $ac_n "checking for memcpy""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_memcpy'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char memcpy(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_memcpy) || defined (__stub___memcpy) +choke me +#else +memcpy(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2621: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_memcpy=yes" +else + rm -rf conftest* + eval "ac_cv_func_memcpy=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'memcpy`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}memcpy.o "; for ac_func in bcopy +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2667: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +fi + +echo $ac_n "checking for memset""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_memset'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char memset(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_memset) || defined (__stub___memset) +choke me +#else +memset(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2720: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_memset=yes" +else + rm -rf conftest* + eval "ac_cv_func_memset=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'memset`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}memset.o "; for ac_func in bzero +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2766: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +fi + +echo $ac_n "checking for getcwd""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_getcwd'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getcwd(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getcwd) || defined (__stub___getcwd) +choke me +#else +getcwd(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2819: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_getcwd=yes" +else + rm -rf conftest* + eval "ac_cv_func_getcwd=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'getcwd`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}getcwd.o "; for ac_func in getwd +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2865: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +fi + +echo $ac_n "checking for getenv""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_getenv'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getenv(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getenv) || defined (__stub___getenv) +choke me +#else +getenv(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2918: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_getenv=yes" +else + rm -rf conftest* + eval "ac_cv_func_getenv=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'getenv`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_GETENV 1 +EOF + +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}env.o " +fi + +echo $ac_n "checking for getutline""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_getutline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getutline(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getutline) || defined (__stub___getutline) +choke me +#else +getutline(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2968: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_getutline=yes" +else + rm -rf conftest* + eval "ac_cv_func_getutline=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'getutline`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}getutline.o "; for ac_func in ttyslot +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3014: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +fi + +echo $ac_n "checking for pututline""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_pututline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pututline(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_pututline) || defined (__stub___pututline) +choke me +#else +pututline(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3067: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_pututline=yes" +else + rm -rf conftest* + eval "ac_cv_func_pututline=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'pututline`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}pututline.o "; for ac_func in ttyslot +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3113: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +fi + +echo $ac_n "checking for setenv""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_setenv'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setenv(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_setenv) || defined (__stub___setenv) +choke me +#else +setenv(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3166: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_setenv=yes" +else + rm -rf conftest* + eval "ac_cv_func_setenv=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'setenv`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_SETENV 1 +EOF + +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}env.o " +fi + +echo $ac_n "checking for sigprocmask""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_sigprocmask'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char sigprocmask(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_sigprocmask) || defined (__stub___sigprocmask) +choke me +#else +sigprocmask(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3216: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_sigprocmask=yes" +else + rm -rf conftest* + eval "ac_cv_func_sigprocmask=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'sigprocmask`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}sigprocmask.o "; for ac_func in sigblock sigsetmask +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3262: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +fi + +echo $ac_n "checking for strchr""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_strchr'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strchr(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strchr) || defined (__stub___strchr) +choke me +#else +strchr(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_strchr=yes" +else + rm -rf conftest* + eval "ac_cv_func_strchr=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'strchr`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}strchr.o "; for ac_func in index +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3361: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +fi + +echo $ac_n "checking for strrchr""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_strrchr'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strrchr(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strrchr) || defined (__stub___strrchr) +choke me +#else +strrchr(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3414: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_strrchr=yes" +else + rm -rf conftest* + eval "ac_cv_func_strrchr=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'strrchr`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}strrchr.o "; for ac_func in rindex +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3460: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +fi + +echo $ac_n "checking for sysconf""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_sysconf'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char sysconf(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_sysconf) || defined (__stub___sysconf) +choke me +#else +sysconf(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3513: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_sysconf=yes" +else + rm -rf conftest* + eval "ac_cv_func_sysconf=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'sysconf`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}sysconf.o "; for ac_func in getdtablesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3559: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +fi + +echo $ac_n "checking for uname""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_uname'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char uname(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_uname) || defined (__stub___uname) +choke me +#else +uname(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3612: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_uname=yes" +else + rm -rf conftest* + eval "ac_cv_func_uname=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'uname`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}uname.o "; for ac_func in gethostname +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +fi + +echo $ac_n "checking for unsetenv""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_func_unsetenv'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char unsetenv(); + +int main() { return 0; } +int t() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_unsetenv) || defined (__stub___unsetenv) +choke me +#else +unsetenv(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3711: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_func_unsetenv=yes" +else + rm -rf conftest* + eval "ac_cv_func_unsetenv=no" +fi +rm -f conftest* + +fi +if eval "test \"`echo '$ac_cv_func_'unsetenv`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_UNSETENV 1 +EOF + +else + echo "$ac_t""no" 1>&6 +MISSING="${MISSING}env.o " +fi + + + +echo $ac_n "checking for nonstandard gettimeofday""... $ac_c" 1>&6 +cat > conftest.$ac_ext < +#endif /* HAVE_SYS_TIME_H */ +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ + +int main() { return 0; } +int t() { +struct timeval tv; +gettimeofday(&tv, NULL) +; return 0; } +EOF +if { (eval echo configure:3752: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + echo "$ac_t""no" 1>&6 +else + rm -rf conftest* + echo "$ac_t""maybe" 1>&6 cat > conftest.$ac_ext < +#endif /* HAVE_SYS_TIME_H */ +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ + +int main() { return 0; } +int t() { +struct timeval tv; +gettimeofday(&tv) +; return 0; } +EOF +if { (eval echo configure:3774: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_ONE_ARG_GETTIMEOFDAY 1 +EOF + echo "$ac_t""yes" 1>&6 +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + +fi +rm -f conftest* + + +# Munge out LOCALBIN and LOCALMAN in canonical (no bletch) form +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \ + >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.10" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir + +trap 'rm -fr `echo "configure.munger libmissing/Makefile libopie/Makefile Makefile.munge:Makefile.in config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@CC@%$CC%g +s%@CPP@%$CPP%g +s%@LN_S@%$LN_S%g +s%@RANLIB@%$RANLIB%g +s%@YACC@%$YACC%g +s%@CHOWN@%$CHOWN%g +s%@SU@%$SU%g +s%@ALT_SU@%$ALT_SU%g +s%@SCHEME@%$SCHEME%g +s%@LOGIN@%$LOGIN%g +s%@FTPD@%$FTPD%g +s%@INFTPD@%$INFTPD%g +s%@EXISTS@%$EXISTS%g +s%@MKDIR@%$MKDIR%g +s%@LIBOBJS@%$LIBOBJS%g +s%@ALLOCA@%$ALLOCA%g +s%@MISSING@%$MISSING%g + +CEOF +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust relative srcdir, etc. for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file +fi; done +rm -f conftest.subs + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +CONFIG_HEADERS=${CONFIG_HEADERS-"config.h"} +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + cp $ac_given_srcdir/$ac_file_in conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. +# Maximum number of lines to put in a single here document. +ac_max_here_lines=12 + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + + + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + +sh configure.munger diff --git a/contrib/opie/configure.in b/contrib/opie/configure.in new file mode 100644 index 0000000..91c1a35 --- /dev/null +++ b/contrib/opie/configure.in @@ -0,0 +1,455 @@ +dnl configure.in: Input for Autoconf +dnl +dnl %%% portions-copyright-cmetz +dnl Portions of this software are Copyright 1996 by Craig Metz, All Rights +dnl Reserved. The Inner Net License Version 2 applies to these portions of +dnl the software. +dnl You should have received a copy of the license with this software. If +dnl you didn't get a copy, you may request one from . +dnl +dnl Portions of this software are Copyright 1995 by Randall Atkinson and Dan +dnl McDonald, All Rights Reserved. All Rights under this copyright are assigned +dnl to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +dnl License Agreement applies to this software. +dnl +dnl History: +dnl +dnl Modified by cmetz for OPIE 2.3. Removed redundant memset/memcpy. +dnl Changed ls -g test around. Changed logindevperm/fbtab defines. +dnl Added check for /etc/environment and /etc/src.sh. Check for +dnl /var/adm/sulog. Check for {get,put}utxline, provide libmissing +dnl versionf of {get,put}utline. Added --enable option for anonymous +dnl FTP. Got rid of a few unneeded checks. Check for functions only +dnl used by libmissing only if the replacement function that needs +dnl them is itself needed. +dnl Modified by cmetz for OPIE 2.22. Check for Solaris drain bamaged ls. +dnl Check for setlogin(). Removed duplicate checks for some funcs. +dnl Modified by cmetz for OPIE 2.21. Filename must be in utmp[x]/wtmp[x] +dnl defines. +dnl Modified by cmetz for OPIE 2.2. Misc changes. Changed for libmissing +dnl support and building its target object list. Changed to support +dnl FUNCTION declaration et al. Added a LOT of checks and a LOT of +dnl fixes. +dnl Created at NRL for OPIE 2.1. + +AC_INIT(README) +AC_CONFIG_HEADER(config.h) +AC_ARG_ENABLE(access-file, [ --enable-access-file=PATH Use the OPIE access file PATH as a transition aid], AC_DEFINE_UNQUOTED(PATH_ACCESS_FILE, "$enable_access_file") echo "Using the access file in $enable_access_file -- don't say we didn't warn you!") +AC_ARG_ENABLE(anonymous-ftp, [ --enable-anonymous-ftp Enable anonymous FTP support], AC_DEFINE(DOANONYMOUS) echo "Enabling anonymous FTP support in ftp -- don't say we didn't warn you!") + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CPP +AC_PROG_LN_S +AC_PROG_RANLIB +AC_PROG_YACC + +AC_AIX +AC_ISC_POSIX +AC_MINIX + +AC_C_CROSS + +dnl We'd put PATH in these checks, but it turns out that autoconf doesn't +dnl work as documented when it comes to the colon separator... + +AC_PATH_PROG(CHOWN, chown, /bin/chown, /usr/bin /bin /usr/sbin /sbin /usr/etc /etc) + +AC_PATH_PROG(SU, su, /bin/su, /usr/bin /bin) +AC_PATH_PROG(ALT_SU, su,, /usr/sbin /sbin) + +AC_PATH_PROG(SCHEME, scheme,, /usr/lib/iaf/scheme) +AC_PATH_PROG(LOGIN, login, /bin/login, /usr/bin /bin) +dnl AC_DEFINE_UNQUOTED(PATH_LOGIN, "$LOGIN") + +if test ! -z "$SCHEME"; +then + LOGIN="$SCHEME"; +fi + +AC_PATH_PROG(FTPD, ftpd,, /usr/libexec /usr/etc /etc /usr/sbin /sbin /usr/lbin) +AC_PATH_PROG(INFTPD, in.ftpd,, /usr/libexec /usr/etc /etc /usr/sbin /sbin /usr/lbin) + +if test -z "$FTPD" +then + if test ! -z "$INFTPD" + then + FTPD="$INFTPD" + fi +fi + +AC_MSG_CHECKING(for default PATH entries) +default_path="" +save_IFS="$IFS" +IFS=" " +for i in /usr/bin /bin /usr/ucb /usr/sbin /usr/bsd /sbin /usr/bin/X11 /etc /usr/local/X11/bin /usr/X11R6/bin /your-system-is-broken +do + IFS=":" + for j in $PATH + do + if test "$i" = "$j" + then + if test -d "$i" + then + if test -z "$default_path" + then + default_path="$i" + else + default_path="$default_path:$i" + fi + fi + fi + done + IFS=" " +done +AC_DEFINE_UNQUOTED(DEFAULT_PATH, "$default_path") +AC_MSG_RESULT($default_path) + +AC_MSG_CHECKING(for test -e flag) +if sh config.testeflag +then + result=yes + EXISTS="-e" +else + result=no + EXISTS="-f" +fi +AC_SUBST(EXISTS) +AC_MSG_RESULT($result) + +AC_MSG_CHECKING(for mkdir -p flag) +if test -d config.tmpdir +then + rmdir config.tmpdir/foo/bar >/dev/null 2>/dev/null + rmdir config.tmpdir/foo >/dev/null 2>/dev/null + rmdir config.tmpdir >/dev/null 2>/dev/null +fi + +result=no +if mkdir -p config.tmpdir/foo/bar >/dev/null 2>/dev/null +then + if test -d config.tmpdir + then + if test -d config.tmpdir/foo + then + if test -d config.tmpdir/foo/bar + then + result=yes + rmdir config.tmpdir/foo/bar >/dev/null 2>/dev/null + fi + rmdir config.tmpdir/foo >/dev/null 2>/dev/null + fi + rmdir config.tmpdir >/dev/null 2>/dev/null + fi +fi + +if test "$result" = yes +then + MKDIR="mkdir -p" +else + MKDIR="mkdir" +fi +AC_SUBST(MKDIR) +AC_MSG_RESULT($result) + +AC_MSG_CHECKING(for ls group field) +lsg=`/bin/ls -ldg / | wc -w | awk '{print $1}'`; +ls=`/bin/ls -ld / | wc -w | awk '{print $1}'`; +result="no" +if test $ls = 9; +then + result="yes" +else + if test "$ls" = 8 -a "$lsg" = 9; + then + result="yes, with -g" + AC_DEFINE(HAVE_LS_G_FLAG) + fi +fi +AC_MSG_RESULT($result) + +dnl Checks for various system characteristics +AC_MSG_CHECKING(for /etc/default/login) +if test $EXISTS /etc/default/login +then + result=yes + AC_DEFINE(HAVE_ETC_DEFAULT_LOGIN) +else + result=no +fi +AC_MSG_RESULT($result) + +AC_MSG_CHECKING(for /etc/securetty) +if test $EXISTS /etc/securetty +then + result=yes + AC_DEFINE(HAVE_SECURETTY) +else + result=no +fi +AC_MSG_RESULT($result) + +AC_MSG_CHECKING(for /etc/logindevperm) +if test $EXISTS /etc/logindevperm +then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_LOGIN_PERMFILE, "/etc/logindevperm") +else + AC_MSG_RESULT(no) + + AC_MSG_CHECKING(for /etc/fbtab) + if test $EXISTS /etc/fbtab + then + result=yes + AC_DEFINE(HAVE_LOGIN_PERMFILE, "/etc/fbtab") + else + result=no + fi + AC_MSG_RESULT($result) +fi + +AC_MSG_CHECKING(for /etc/environment) +if test $EXISTS /etc/environment +then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_LOGIN_ENVFILE, "/etc/environment") +else + AC_MSG_RESULT(no) + + AC_MSG_CHECKING(for /etc/src.sh) + if test $EXISTS /etc/src.sh + then + result=yes + AC_DEFINE(HAVE_LOGIN_ENVFILE, "/etc/src.sh") + else + result=no + fi + AC_MSG_RESULT($result) +fi + +AC_MSG_CHECKING(for /etc/shadow) +if test $EXISTS /etc/shadow +then + result=yes + AC_DEFINE(HAVE_ETC_SHADOW) +else + result=no +fi +AC_MSG_RESULT($result) + +AC_MSG_CHECKING(for /var/adm/sulog) +if test $EXISTS /var/adm/sulog +then + result=yes + AC_DEFINE(HAVE_SULOG) +else + result=no +fi +AC_MSG_RESULT($result) + +AC_MSG_CHECKING(mail spool location) +mail_spool="" +for i in /var/mail /usr/mail /var/spool/mail /usr/spool/mail +do + if test -d $i + then + mail_spool="$i" + fi +done +if test -z "$mail_spool" +then + result="not found" +else + result="$mail_spool" + AC_DEFINE_UNQUOTED(PATH_MAIL, "$mail_spool") +fi +AC_MSG_RESULT($result) + +dnl AC_MSG_CHECKING(where your system puts the utmp file) +dnl utmp_path="" +dnl for i in /var/run /var/adm /usr/adm /etc +dnl do +dnl if test $EXISTS $i/utmp +dnl then +dnl utmp_path="$i" +dnl fi +dnl done +dnl if test -z "$utmp_path" +dnl then +dnl result="not found" +dnl else +dnl result="$utmp_path" +dnl AC_DEFINE_UNQUOTED(PATH_UTMP_AC, "$utmp_path/utmp") +dnl fi +dnl AC_MSG_RESULT($result) + +dnl AC_MSG_CHECKING(where your system puts the wtmp file) +dnl wtmp_path="" +dnl for i in /var/run /var/adm /usr/adm /etc +dnl do +dnl if test $EXISTS $i/wtmp +dnl then +dnl wtmp_path="$i" +dnl fi +dnl done +dnl if test -z "$wtmp_path" +dnl then +dnl result="not found" +dnl else +dnl result="$wtmp_path" +dnl AC_DEFINE_UNQUOTED(PATH_WTMP_AC, "$wtmp_path/wtmp") +dnl fi +dnl AC_MSG_RESULT($result) + +AC_MSG_CHECKING(whether the system profile displays the motd) +result=no +if test $EXISTS /etc/profile +then + if grep motd /etc/profile >/dev/null 2>/dev/null + then + result=yes + fi +fi +if test "$result" = yes +then + AC_DEFINE(HAVE_MOTD_IN_PROFILE) +fi +AC_MSG_RESULT($result) + +AC_MSG_CHECKING(whether the system profile checks for mail) +result=no +if test $EXISTS /etc/profile +then + if grep 'mail\.' /etc/profile >/dev/null 2>/dev/null + then + result=yes + fi +fi +if test "$result" = yes +then + AC_DEFINE(HAVE_MAILCHECK_IN_PROFILE) +fi +AC_MSG_RESULT($result) + +dnl Random checks +AC_C_CONST + +AC_MSG_CHECKING(to see if your compiler can handle void arguments) +AC_TRY_COMPILE(foo(void) { },, AC_DEFINE(HAVE_VOIDARG) AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) + +AC_MSG_CHECKING(to see if your compiler can handle void return values) +AC_TRY_COMPILE(void foo() { },, AC_DEFINE(HAVE_VOIDRET) AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) + +AC_MSG_CHECKING(to see if your compiler can handle void pointers) +AC_TRY_COMPILE(foo() { void *bar = (void *)0x42; bar = bar + 1; },, AC_DEFINE(HAVE_VOIDPTR) AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) + +AC_MSG_CHECKING(to see if your compiler can handle ANSI argument lists) +AC_TRY_COMPILE(int foo(int bar, int baz) { return 0; },, AC_DEFINE(HAVE_ANSIDECL) AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) + +AC_MSG_CHECKING(to see if your compiler can handle ANSI prototypes) +AC_TRY_COMPILE(extern int foo(int, int);,, AC_DEFINE(HAVE_ANSIPROTO) AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) + +AC_MSG_CHECKING(to see if your compiler can handle ANSI variable arguments) +AC_TRY_COMPILE([#include +int foo(int arg, ...) { + va_list ap; + va_start(ap, arg); + va_end(ap); + return 0; +}],, AC_DEFINE(HAVE_ANSISTDARG) AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) + +AC_MSG_CHECKING(to see if you have an ANSI-style sprintf) +AC_TRY_RUN([#include +int main(argc, argv) +int argc; +char *argv[]; +{ + char buf[5]; + int i = 2; + i += sprintf(buf, "1234"); + return (i == 6) ? 0 : -1; +}], AC_DEFINE(HAVE_ANSISPRINTF) AC_MSG_RESULT(yes), AC_MSG_RESULT(no), AC_MSG_RESULT(no)) + +dnl Checks for libraries. +AC_CHECK_LIB(crypt, crypt) +AC_CHECK_LIB(nsl, gethostname) +AC_CHECK_LIB(posix, main) +AC_CHECK_LIB(socket, socket) + +dnl Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS(crypt.h fcntl.h limits.h termios.h sys/file.h sys/ioctl.h sys/time.h syslog.h unistd.h paths.h shadow.h signal.h sys/signal.h lastlog.h sys/utsname.h pwd.h sys/param.h string.h stdlib.h utmpx.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +dnl AC_TYPE_UID_T +dnl AC_TYPE_OFF_T +dnl AC_TYPE_PID_T +dnl AC_STRUCT_ST_BLKSIZE +dnl AC_STRUCT_TM + +AC_MSG_CHECKING(for ut_pid in struct utmp) +AC_TRY_COMPILE([#include +#include ], [struct utmp foo; return (int)foo.ut_pid;], AC_DEFINE(HAVE_UT_PID) AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) +AC_MSG_CHECKING(for ut_type in struct utmp) +AC_TRY_COMPILE([#include +#include ], [struct utmp foo; return (int)foo.ut_type;], AC_DEFINE(HAVE_UT_TYPE) AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) +AC_MSG_CHECKING(for ut_name in struct utmp) +AC_TRY_COMPILE([#include +#include ], [struct utmp foo; return (int)foo.ut_name[0];], AC_DEFINE(HAVE_UT_NAME) AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) +dnl AC_MSG_CHECKING(for ut_user in struct utmp) +dnl AC_TRY_COMPILE([#include +dnl #include ], [struct utmp foo; return (int)foo.ut_user[0];], AC_DEFINE(HAVE_UT_USER) AC_MSG_RESULT(yes), AC_MSG_RESULT(no)) +AC_DEFINE(HAVE_UT_HOST) + +dnl Checks for library functions. +dnl AC_PROG_GCC_TRADITIONAL +AC_TYPE_SIGNAL +AC_CHECK_FUNCS(gettimeofday socket strftime strstr setpriority seteuid setreuid setegid setregid setresuid setresgid getttynam sysconf setvbuf getspent endspent setgroups getgroups fpurge setlogin lstat getutxline pututxline) + +dnl Libmissing... +AC_FUNC_MEMCMP +AC_FUNC_ALLOCA +AC_REPLACE_FUNCS(getusershell sigaddset sigemptyset strerror strncasecmp) +MISSING="$LIBOBJS $ALLOCA " +AC_CHECK_FUNC(atexit,, MISSING="${MISSING}atexit.o ") +AC_CHECK_FUNC(entutent,, MISSING="${MISSING}endutent.o ") +AC_CHECK_FUNC(memcpy,, MISSING="${MISSING}memcpy.o "; AC_CHECK_FUNCS(bcopy)) +AC_CHECK_FUNC(memset,, MISSING="${MISSING}memset.o "; AC_CHECK_FUNCS(bzero)) +AC_CHECK_FUNC(getcwd,, MISSING="${MISSING}getcwd.o "; AC_CHECK_FUNCS(getwd)) +AC_CHECK_FUNC(getenv, AC_DEFINE(HAVE_GETENV), MISSING="${MISSING}env.o ") +AC_CHECK_FUNC(getutline,, MISSING="${MISSING}getutline.o "; AC_CHECK_FUNCS(ttyslot)) +AC_CHECK_FUNC(pututline,, MISSING="${MISSING}pututline.o "; AC_CHECK_FUNCS(ttyslot)) +AC_CHECK_FUNC(setenv, AC_DEFINE(HAVE_SETENV), MISSING="${MISSING}env.o ") +AC_CHECK_FUNC(sigprocmask,, MISSING="${MISSING}sigprocmask.o "; AC_CHECK_FUNCS(sigblock sigsetmask)) +AC_CHECK_FUNC(strchr,, MISSING="${MISSING}strchr.o "; AC_CHECK_FUNCS(index)) +AC_CHECK_FUNC(strrchr,, MISSING="${MISSING}strrchr.o "; AC_CHECK_FUNCS(rindex)) +AC_CHECK_FUNC(sysconf,, MISSING="${MISSING}sysconf.o "; AC_CHECK_FUNCS(getdtablesize)) +AC_CHECK_FUNC(uname,, MISSING="${MISSING}uname.o "; AC_CHECK_FUNCS(gethostname)) +AC_CHECK_FUNC(unsetenv, AC_DEFINE(HAVE_UNSETENV), MISSING="${MISSING}env.o ") +AC_SUBST(MISSING) + +AC_MSG_CHECKING(for nonstandard gettimeofday) +AC_TRY_COMPILE([ +#if HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +], +[struct timeval tv; +gettimeofday(&tv, NULL)], AC_MSG_RESULT(no), AC_MSG_RESULT(maybe) AC_TRY_COMPILE([ +#if HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +], +[struct timeval tv; +gettimeofday(&tv)], AC_DEFINE(HAVE_ONE_ARG_GETTIMEOFDAY) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))) + +# Munge out LOCALBIN and LOCALMAN in canonical (no bletch) form +AC_OUTPUT(configure.munger libmissing/Makefile libopie/Makefile Makefile.munge:Makefile.in) +sh configure.munger diff --git a/contrib/opie/configure.munger.in b/contrib/opie/configure.munger.in new file mode 100644 index 0000000..25f5ebf --- /dev/null +++ b/contrib/opie/configure.munger.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +mandir=@mandir@ + +LOCALBIN=$bindir +LOCALMAN=$mandir + +echo "" +echo "Binaries are going to be installed into $LOCALBIN," +echo "Manual pages are going to be installed into $LOCALMAN." +echo "" +echo "creating Makefile" +cat Makefile.munge | sed s:@LOCALMAN@:$LOCALMAN:g | sed s:@LOCALBIN@:$LOCALBIN:g > Makefile +echo "" +echo "Have you read the README file?" diff --git a/contrib/opie/ftpcmd.y b/contrib/opie/ftpcmd.y new file mode 100644 index 0000000..10ef24f --- /dev/null +++ b/contrib/opie/ftpcmd.y @@ -0,0 +1,1286 @@ +/* ftpcmd.y: yacc parser for the FTP daemon. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Modified by cmetz for OPIE 2.3. Moved LS_COMMAND here. + Modified by cmetz for OPIE 2.2. Fixed a *lot* of warnings. + Use FUNCTION declaration et al. Removed useless strings. + Changed some char []s to char *s. Deleted comment address. + Changed tmpline references to be more pure-pointer + references. Changed tmpline declaration back to char []. + Modified at NRL for OPIE 2.1. Minor changes for autoconf. + Modified at NRL for OPIE 2.01. Added forward declaration for sitetab[] + -- fixes problems experienced by bison users. Merged in new + PORT attack fixes from Hobbit. + Modified at NRL for OPIE 2.0. + Originally from BSD. +*/ +/* + * Copyright (c) 1985, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ftpcmd.y 5.24 (Berkeley) 2/25/91 + */ + +/* + * Grammar for FTP commands. + * See RFC 959. + */ + +%{ +#include "opie_cfg.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if TM_IN_SYS_TIME +#include +#else /* TM_IN_SYS_TIME */ +#include +#endif /* TM_IN_SYS_TIME */ +#include +#include +#include +#include +#include +#include + +#include "opie.h" + +#if HAVE_LS_G_FLAG +#define LS_COMMAND "/bin/ls -lgA" +#else /* HAVE_LS_G_FLAG */ +#define LS_COMMAND "/bin/ls -lA" +#endif /* HAVE_LS_G_FLAG */ + +extern struct sockaddr_in data_dest; +extern struct sockaddr_in his_addr; +extern int logged_in; +extern struct passwd *pw; +extern int guest; +extern int type; +extern int form; +extern int debug; +extern int timeout; +extern int maxtimeout; +extern int pdata; +extern char *remotehost; +extern char *proctitle; +extern char *globerr; +extern int usedefault; +extern int transflag; +extern char tmpline[]; +char **ftpglob(); + +VOIDRET dologout __P((int)); +VOIDRET upper __P((char *)); +VOIDRET nack __P((char *)); +VOIDRET opiefatal __P((char *)); + +VOIDRET pass __P((char *)); +int user __P((char *)); +VOIDRET passive __P((void)); +VOIDRET retrieve __P((char *, char *)); +VOIDRET store __P((char *, char *, int)); +VOIDRET send_file_list __P((char *)); +VOIDRET statfilecmd __P((char *)); +VOIDRET statcmd __P((void)); +VOIDRET delete __P((char *)); +VOIDRET renamecmd __P((char *, char *)); +VOIDRET cwd __P((char *)); +VOIDRET makedir __P((char *)); +VOIDRET removedir __P((char *)); +VOIDRET pwd __P((void)); + +VOIDRET sizecmd __P((char *)); + +off_t restart_point; + +static int cmd_type; +static int cmd_form; +static int cmd_bytesz; +static unsigned short cliport = 0; +char cbuf[512]; +char *fromname; + +struct tab { + char *name; + short token; + short state; + short implemented; /* 1 if command is implemented */ + char *help; +}; + +VOIDRET help __P((struct tab *, char *)); + +struct tab cmdtab[], sitetab[]; + +%} + +%token + A B C E F I + L N P R S T + + SP CRLF COMMA STRING NUMBER + + USER PASS ACCT REIN QUIT PORT + PASV TYPE STRU MODE RETR STOR + APPE MLFL MAIL MSND MSOM MSAM + MRSQ MRCP ALLO REST RNFR RNTO + ABOR DELE CWD LIST NLST SITE + STAT HELP NOOP MKD RMD PWD + CDUP STOU SMNT SYST SIZE MDTM + + UMASK IDLE CHMOD + + LEXERR + +%start cmd_list + +%% + +cmd_list: /* empty */ + | cmd_list cmd + = { + fromname = (char *) 0; + restart_point = (off_t) 0; + } + | cmd_list rcmd + ; + +cmd: USER SP username CRLF + = { + user((char *) $3); + free((char *) $3); + } + | PASS SP password CRLF + = { + pass((char *) $3); + free((char *) $3); + } + | PORT check_login SP host_port CRLF + = { + usedefault = 0; + if (pdata >= 0) { + (void) close(pdata); + pdata = -1; + } +/* H* port fix, part B: admonish the twit. + Also require login before PORT works */ + if ($2) { + if ((cliport > 1023) && (data_dest.sin_addr.s_addr > 0)) { + reply(200, "PORT command successful."); + } else { + syslog (LOG_WARNING, "refused %s from %s", + cbuf, remotehost); + reply(500, "You've GOT to be joking."); + } + } + } +/* | PASV CRLF + = { + passive(); + } */ + | PASV check_login CRLF + = { +/* Require login for PASV, too. This actually fixes a bug -- telnet to an + unfixed wu-ftpd and type PASV first off, and it crashes! */ + if ($2) { + passive(); + } + } + | TYPE SP type_code CRLF + = { + switch (cmd_type) { + + case TYPE_A: + if (cmd_form == FORM_N) { + reply(200, "Type set to A."); + type = cmd_type; + form = cmd_form; + } else + reply(504, "Form must be N."); + break; + + case TYPE_E: + reply(504, "Type E not implemented."); + break; + + case TYPE_I: + reply(200, "Type set to I."); + type = cmd_type; + break; + + case TYPE_L: +#if NBBY == 8 + if (cmd_bytesz == 8) { + reply(200, + "Type set to L (byte size 8)."); + type = cmd_type; + } else + reply(504, "Byte size must be 8."); +#else /* NBBY == 8 */ + UNIMPLEMENTED for NBBY != 8 +#endif /* NBBY == 8 */ + } + } + | STRU SP struct_code CRLF + = { + switch ($3) { + + case STRU_F: + reply(200, "STRU F ok."); + break; + + default: + reply(504, "Unimplemented STRU type."); + } + } + | MODE SP mode_code CRLF + = { + switch ($3) { + + case MODE_S: + reply(200, "MODE S ok."); + break; + + default: + reply(502, "Unimplemented MODE type."); + } + } + | ALLO SP NUMBER CRLF + = { + reply(202, "ALLO command ignored."); + } + | ALLO SP NUMBER SP R SP NUMBER CRLF + = { + reply(202, "ALLO command ignored."); + } + | RETR check_login SP pathname CRLF + = { + if ($2 && $4) + retrieve((char *) 0, (char *) $4); + if ($4) + free((char *) $4); + } + | STOR check_login SP pathname CRLF + = { + if ($2 && $4) + store((char *) $4, "w", 0); + if ($4) + free((char *) $4); + } + | APPE check_login SP pathname CRLF + = { + if ($2 && $4) + store((char *) $4, "a", 0); + if ($4) + free((char *) $4); + } + | NLST check_login CRLF + = { + if ($2) + send_file_list("."); + } + | NLST check_login SP STRING CRLF + = { + if ($2 && $4) + send_file_list((char *) $4); + if ($4) + free((char *) $4); + } + | LIST check_login CRLF + = { + if ($2) + retrieve(LS_COMMAND, ""); + } + | LIST check_login SP pathname CRLF + = { + if ($2 && $4) + { + char buffer[sizeof(LS_COMMAND)+3]; + strcpy(buffer, LS_COMMAND); + strcat(buffer, " %s"); + retrieve(buffer, (char *) $4); + } + if ($4) + free((char *) $4); + } + | STAT check_login SP pathname CRLF + = { + if ($2 && $4) + statfilecmd((char *) $4); + if ($4) + free((char *) $4); + } + | STAT CRLF + = { + statcmd(); + } + | DELE check_login SP pathname CRLF + = { + if ($2 && $4) + delete((char *) $4); + if ($4) + free((char *) $4); + } + | RNTO SP pathname CRLF + = { + if (fromname) { + renamecmd(fromname, (char *) $3); + free(fromname); + fromname = (char *) 0; + } else { + reply(503, "Bad sequence of commands."); + } + free((char *) $3); + } + | ABOR CRLF + = { + reply(225, "ABOR command successful."); + } + | CWD check_login CRLF + = { + if ($2) + cwd(pw->pw_dir); + } + | CWD check_login SP pathname CRLF + = { + if ($2 && $4) + cwd((char *) $4); + if ($4) + free((char *) $4); + } + | HELP CRLF + = { + help(cmdtab, (char *) 0); + } + | HELP SP STRING CRLF + = { + register char *cp = (char *)$3; + + if (strncasecmp(cp, "SITE", 4) == 0) { + cp = (char *)$3 + 4; + if (*cp == ' ') + cp++; + if (*cp) + help(sitetab, cp); + else + help(sitetab, (char *) 0); + } else + help(cmdtab, (char *) $3); + } + | NOOP CRLF + = { + reply(200, "NOOP command successful."); + } + | MKD check_login SP pathname CRLF + = { + if ($2 && $4) + makedir((char *) $4); + if ($4) + free((char *) $4); + } + | RMD check_login SP pathname CRLF + = { + if ($2 && $4) + removedir((char *) $4); + if ($4) + free((char *) $4); + } + | PWD check_login CRLF + = { + if ($2) + pwd(); + } + | CDUP check_login CRLF + = { + if ($2) + cwd(".."); + } + | SITE SP HELP CRLF + = { + help(sitetab, (char *) 0); + } + | SITE SP HELP SP STRING CRLF + = { + help(sitetab, (char *) $5); + } + | SITE SP UMASK check_login CRLF + = { + int oldmask; + + if ($4) { + oldmask = umask(0); + (void) umask(oldmask); + reply(200, "Current UMASK is %03o", oldmask); + } + } + | SITE SP UMASK check_login SP octal_number CRLF + = { + int oldmask; + + if ($4) { + if (($6 == -1) || ($6 > 0777)) { + reply(501, "Bad UMASK value"); + } else { + oldmask = umask($6); + reply(200, + "UMASK set to %03o (was %03o)", + $6, oldmask); + } + } + } + | SITE SP CHMOD check_login SP octal_number SP pathname CRLF + = { + if ($4 && $8) { + if ($6 > 0777) + reply(501, + "CHMOD: Mode value must be between 0 and 0777"); + else if (chmod((char *) $8, $6) < 0) + perror_reply(550, (char *) $8); + else + reply(200, "CHMOD command successful."); + } + if ($8) + free((char *) $8); + } + | SITE SP IDLE CRLF + = { + reply(200, + "Current IDLE time limit is %d seconds; max %d", + timeout, maxtimeout); + } + | SITE SP IDLE SP NUMBER CRLF + = { + if ($5 < 30 || $5 > maxtimeout) { + reply(501, + "Maximum IDLE time must be between 30 and %d seconds", + maxtimeout); + } else { + timeout = $5; + (void) alarm((unsigned) timeout); + reply(200, + "Maximum IDLE time set to %d seconds", + timeout); + } + } + | STOU check_login SP pathname CRLF + = { + if ($2 && $4) + store((char *) $4, "w", 1); + if ($4) + free((char *) $4); + } + | SYST CRLF + = { +#ifdef unix +#ifdef BSD + reply(215, "UNIX Type: L%d Version: BSD-%d", + NBBY, BSD); +#else /* BSD */ + reply(215, "UNIX Type: L%d", NBBY); +#endif /* BSD */ +#else /* unix */ + reply(215, "UNKNOWN Type: L%d", NBBY); +#endif /* unix */ + } + + /* + * SIZE is not in RFC959, but Postel has blessed it and + * it will be in the updated RFC. + * + * Return size of file in a format suitable for + * using with RESTART (we just count bytes). + */ + | SIZE check_login SP pathname CRLF + = { + if ($2 && $4) + sizecmd((char *) $4); + if ($4) + free((char *) $4); + } + + /* + * MDTM is not in RFC959, but Postel has blessed it and + * it will be in the updated RFC. + * + * Return modification time of file as an ISO 3307 + * style time. E.g. YYYYMMDDHHMMSS or YYYYMMDDHHMMSS.xxx + * where xxx is the fractional second (of any precision, + * not necessarily 3 digits) + */ + | MDTM check_login SP pathname CRLF + = { + if ($2 && $4) { + struct stat stbuf; + if (stat((char *) $4, &stbuf) < 0) + perror_reply(550, (char *) $4); + else if ((stbuf.st_mode&S_IFMT) != S_IFREG) { + reply(550, "%s: not a plain file.", + (char *) $4); + } else { + register struct tm *t; + struct tm *gmtime(); + t = gmtime(&stbuf.st_mtime); + reply(213, + "19%02d%02d%02d%02d%02d%02d", + t->tm_year, t->tm_mon+1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + } + } + if ($4) + free((char *) $4); + } + | QUIT CRLF + = { + reply(221, "Goodbye."); + dologout(0); + } + | error CRLF + = { + yyerrok; + } + ; +rcmd: RNFR check_login SP pathname CRLF + = { + char *renamefrom(); + + restart_point = (off_t) 0; + if ($2 && $4) { + fromname = renamefrom((char *) $4); + if (fromname == (char *) 0 && $4) { + free((char *) $4); + } + } + } + | REST SP byte_size CRLF + = { + long atol(); + + fromname = (char *) 0; + restart_point = $3; + reply(350, "Restarting at %ld. %s", restart_point, + "Send STORE or RETRIEVE to initiate transfer."); + } + ; + +username: STRING + ; + +password: /* empty */ + = { + *(char **)&($$) = (char *)calloc(1, sizeof(char)); + } + | STRING + ; + +byte_size: NUMBER + ; + +host_port: NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA + NUMBER COMMA NUMBER + = { + register char *a, *p; + + a = (char *)&data_dest.sin_addr; + a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7; + +/* H* port fix, part A-1: Check the args against the client addr */ + p = (char *)&his_addr.sin_addr; + if (memcmp (a, p, sizeof (data_dest.sin_addr))) + memset (a, 0, sizeof (data_dest.sin_addr)); /* XXX */ + + p = (char *)&data_dest.sin_port; + +/* H* port fix, part A-2: only allow client ports in "user space" */ + p[0] = 0; p[1] = 0; + cliport = ($9 << 8) + $11; + if (cliport > 1023) { + p[0] = $9; p[1] = $11; + } + + p[0] = $9; p[1] = $11; + data_dest.sin_family = AF_INET; + } + ; + +form_code: N + = { + $$ = FORM_N; + } + | T + = { + $$ = FORM_T; + } + | C + = { + $$ = FORM_C; + } + ; + +type_code: A + = { + cmd_type = TYPE_A; + cmd_form = FORM_N; + } + | A SP form_code + = { + cmd_type = TYPE_A; + cmd_form = $3; + } + | E + = { + cmd_type = TYPE_E; + cmd_form = FORM_N; + } + | E SP form_code + = { + cmd_type = TYPE_E; + cmd_form = $3; + } + | I + = { + cmd_type = TYPE_I; + } + | L + = { + cmd_type = TYPE_L; + cmd_bytesz = NBBY; + } + | L SP byte_size + = { + cmd_type = TYPE_L; + cmd_bytesz = $3; + } + /* this is for a bug in the BBN ftp */ + | L byte_size + = { + cmd_type = TYPE_L; + cmd_bytesz = $2; + } + ; + +struct_code: F + = { + $$ = STRU_F; + } + | R + = { + $$ = STRU_R; + } + | P + = { + $$ = STRU_P; + } + ; + +mode_code: S + = { + $$ = MODE_S; + } + | B + = { + $$ = MODE_B; + } + | C + = { + $$ = MODE_C; + } + ; + +pathname: pathstring + = { + /* + * Problem: this production is used for all pathname + * processing, but only gives a 550 error reply. + * This is a valid reply in some cases but not in others. + */ + if (logged_in && $1 && strncmp((char *) $1, "~", 1) == 0) { + *(char **)&($$) = *ftpglob((char *) $1); + if (globerr != NULL) { + reply(550, globerr); +/* $$ = NULL; */ + $$ = 0; + } + free((char *) $1); + } else + $$ = $1; + } + ; + +pathstring: STRING + ; + +octal_number: NUMBER + = { + register int ret, dec, multby, digit; + + /* + * Convert a number that was read as decimal number + * to what it would be if it had been read as octal. + */ + dec = $1; + multby = 1; + ret = 0; + while (dec) { + digit = dec%10; + if (digit > 7) { + ret = -1; + break; + } + ret += digit * multby; + multby *= 8; + dec /= 10; + } + $$ = ret; + } + ; + +check_login: /* empty */ + = { + if (logged_in) + $$ = 1; + else { + reply(530, "Please login with USER and PASS."); + $$ = 0; + } + } + ; + +%% + +extern jmp_buf errcatch; + +#define CMD 0 /* beginning of command */ +#define ARGS 1 /* expect miscellaneous arguments */ +#define STR1 2 /* expect SP followed by STRING */ +#define STR2 3 /* expect STRING */ +#define OSTR 4 /* optional SP then STRING */ +#define ZSTR1 5 /* SP then optional STRING */ +#define ZSTR2 6 /* optional STRING after SP */ +#define SITECMD 7 /* SITE command */ +#define NSTR 8 /* Number followed by a string */ + +struct tab cmdtab[] = { /* In order defined in RFC 765 */ + { "USER", USER, STR1, 1, " username" }, + { "PASS", PASS, ZSTR1, 1, " password" }, + { "ACCT", ACCT, STR1, 0, "(specify account)" }, + { "SMNT", SMNT, ARGS, 0, "(structure mount)" }, + { "REIN", REIN, ARGS, 0, "(reinitialize server state)" }, + { "QUIT", QUIT, ARGS, 1, "(terminate service)", }, + { "PORT", PORT, ARGS, 1, " b0, b1, b2, b3, b4" }, + { "PASV", PASV, ARGS, 1, "(set server in passive mode)" }, + { "TYPE", TYPE, ARGS, 1, " [ A | E | I | L ]" }, + { "STRU", STRU, ARGS, 1, "(specify file structure)" }, + { "MODE", MODE, ARGS, 1, "(specify transfer mode)" }, + { "RETR", RETR, STR1, 1, " file-name" }, + { "STOR", STOR, STR1, 1, " file-name" }, + { "APPE", APPE, STR1, 1, " file-name" }, + { "MLFL", MLFL, OSTR, 0, "(mail file)" }, + { "MAIL", MAIL, OSTR, 0, "(mail to user)" }, + { "MSND", MSND, OSTR, 0, "(mail send to terminal)" }, + { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" }, + { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" }, + { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" }, + { "MRCP", MRCP, STR1, 0, "(mail recipient)" }, + { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" }, + { "REST", REST, ARGS, 1, "(restart command)" }, + { "RNFR", RNFR, STR1, 1, " file-name" }, + { "RNTO", RNTO, STR1, 1, " file-name" }, + { "ABOR", ABOR, ARGS, 1, "(abort operation)" }, + { "DELE", DELE, STR1, 1, " file-name" }, + { "CWD", CWD, OSTR, 1, "[ directory-name ]" }, + { "XCWD", CWD, OSTR, 1, "[ directory-name ]" }, + { "LIST", LIST, OSTR, 1, "[ path-name ]" }, + { "NLST", NLST, OSTR, 1, "[ path-name ]" }, + { "SITE", SITE, SITECMD, 1, "site-cmd [ arguments ]" }, + { "SYST", SYST, ARGS, 1, "(get type of operating system)" }, + { "STAT", STAT, OSTR, 1, "[ path-name ]" }, + { "HELP", HELP, OSTR, 1, "[ ]" }, + { "NOOP", NOOP, ARGS, 1, "" }, + { "MKD", MKD, STR1, 1, " path-name" }, + { "XMKD", MKD, STR1, 1, " path-name" }, + { "RMD", RMD, STR1, 1, " path-name" }, + { "XRMD", RMD, STR1, 1, " path-name" }, + { "PWD", PWD, ARGS, 1, "(return current directory)" }, + { "XPWD", PWD, ARGS, 1, "(return current directory)" }, + { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" }, + { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" }, + { "STOU", STOU, STR1, 1, " file-name" }, + { "SIZE", SIZE, OSTR, 1, " path-name" }, + { "MDTM", MDTM, OSTR, 1, " path-name" }, + { NULL, 0, 0, 0, 0 } +}; + +struct tab sitetab[] = { + { "UMASK", UMASK, ARGS, 1, "[ umask ]" }, + { "IDLE", IDLE, ARGS, 1, "[ maximum-idle-time ]" }, + { "CHMOD", CHMOD, NSTR, 1, " mode file-name" }, + { "HELP", HELP, OSTR, 1, "[ ]" }, + { NULL, 0, 0, 0, 0 } +}; + +struct tab *lookup FUNCTION((p, cmd), register struct tab *p AND char *cmd) +{ + + for (; p->name != NULL; p++) + if (strcmp(cmd, p->name) == 0) + return (p); + return (0); +} + +#include + +/* + * getline - a hacked up version of fgets to ignore TELNET escape codes. + */ +char *getline FUNCTION((s, n, iop), char *s AND int n AND FILE *iop) +{ + register c; + register char *cs; + + cs = s; +/* tmpline may contain saved command from urgent mode interruption */ + for (c = 0; *(tmpline + c) && --n > 0; ++c) { + *cs++ = *(tmpline + c); + if (*(tmpline + c) == '\n') { + *cs++ = '\0'; + if (debug) + syslog(LOG_DEBUG, "command: %s", s); + *tmpline = '\0'; + return(s); + } + if (c == 0) + *tmpline = '\0'; + } + while ((c = getc(iop)) != EOF) { + c &= 0377; + if (c == IAC) { + if ((c = getc(iop)) != EOF) { + c &= 0377; + switch (c) { + case WILL: + case WONT: + c = getc(iop); + printf("%c%c%c", IAC, DONT, 0377&c); + (void) fflush(stdout); + continue; + case DO: + case DONT: + c = getc(iop); + printf("%c%c%c", IAC, WONT, 0377&c); + (void) fflush(stdout); + continue; + case IAC: + break; + default: + continue; /* ignore command */ + } + } + } + *cs++ = c; + if (--n <= 0 || c == '\n') + break; + } + if (c == EOF && cs == s) + return (NULL); + *cs++ = '\0'; + if (debug) + syslog(LOG_DEBUG, "command: %s", s); + return (s); +} + +static VOIDRET toolong FUNCTION((input), int input) +{ + time_t now; + + reply(421, "Timeout (%d seconds): closing control connection.", timeout); + (void) time(&now); + syslog(LOG_INFO, "User %s timed out after %d seconds at %s", + (pw ? pw -> pw_name : "unknown"), timeout, ctime(&now)); + dologout(1); +} + +int yylex FUNCTION_NOARGS +{ + static int cpos, state; + register char *cp, *cp2; + register struct tab *p; + int n; + char c, *copy(); + + for (;;) { + switch (state) { + + case CMD: + (void) signal(SIGALRM, toolong); + (void) alarm((unsigned) timeout); + if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) { + reply(221, "You could at least say goodbye."); + dologout(0); + } + (void) alarm(0); +#ifdef SETPROCTITLE + if (strncasecmp(cbuf, "PASS", 4) != NULL) + setproctitle("%s: %s", proctitle, cbuf); +#endif /* SETPROCTITLE */ + if ((cp = strchr(cbuf, '\r'))) { + *cp++ = '\n'; + *cp = '\0'; + } + if ((cp = strpbrk(cbuf, " \n"))) + cpos = cp - cbuf; + if (cpos == 0) + cpos = 4; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + upper(cbuf); + p = lookup(cmdtab, cbuf); + cbuf[cpos] = c; + if (p != 0) { + if (p->implemented == 0) { + nack(p->name); + longjmp(errcatch,0); + /* NOTREACHED */ + } + state = p->state; + *(char **)&yylval = p->name; + return (p->token); + } + break; + + case SITECMD: + if (cbuf[cpos] == ' ') { + cpos++; + return (SP); + } + cp = &cbuf[cpos]; + if ((cp2 = strpbrk(cp, " \n"))) + cpos = cp2 - cbuf; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + upper(cp); + p = lookup(sitetab, cp); + cbuf[cpos] = c; + if (p != 0) { + if (p->implemented == 0) { + state = CMD; + nack(p->name); + longjmp(errcatch,0); + /* NOTREACHED */ + } + state = p->state; + *(char **)&yylval = p->name; + return (p->token); + } + state = CMD; + break; + + case OSTR: + if (cbuf[cpos] == '\n') { + state = CMD; + return (CRLF); + } + /* FALLTHROUGH */ + + case STR1: + case ZSTR1: + dostr1: + if (cbuf[cpos] == ' ') { + cpos++; + state = state == OSTR ? STR2 : ++state; + return (SP); + } + break; + + case ZSTR2: + if (cbuf[cpos] == '\n') { + state = CMD; + return (CRLF); + } + /* FALLTHROUGH */ + + case STR2: + cp = &cbuf[cpos]; + n = strlen(cp); + cpos += n - 1; + /* + * Make sure the string is nonempty and \n terminated. + */ + if (n > 1 && cbuf[cpos] == '\n') { + cbuf[cpos] = '\0'; + *(char **)&yylval = copy(cp); + cbuf[cpos] = '\n'; + state = ARGS; + return (STRING); + } + break; + + case NSTR: + if (cbuf[cpos] == ' ') { + cpos++; + return (SP); + } + if (isdigit(cbuf[cpos])) { + cp = &cbuf[cpos]; + while (isdigit(cbuf[++cpos])) + ; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + yylval = atoi(cp); + cbuf[cpos] = c; + state = STR1; + return (NUMBER); + } + state = STR1; + goto dostr1; + + case ARGS: + if (isdigit(cbuf[cpos])) { + cp = &cbuf[cpos]; + while (isdigit(cbuf[++cpos])) + ; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + yylval = atoi(cp); + cbuf[cpos] = c; + return (NUMBER); + } + switch (cbuf[cpos++]) { + + case '\n': + state = CMD; + return (CRLF); + + case ' ': + return (SP); + + case ',': + return (COMMA); + + case 'A': + case 'a': + return (A); + + case 'B': + case 'b': + return (B); + + case 'C': + case 'c': + return (C); + + case 'E': + case 'e': + return (E); + + case 'F': + case 'f': + return (F); + + case 'I': + case 'i': + return (I); + + case 'L': + case 'l': + return (L); + + case 'N': + case 'n': + return (N); + + case 'P': + case 'p': + return (P); + + case 'R': + case 'r': + return (R); + + case 'S': + case 's': + return (S); + + case 'T': + case 't': + return (T); + + } + break; + + default: + opiefatal("Unknown state in scanner."); + } + yyerror((char *) 0); + state = CMD; + longjmp(errcatch,0); + } +} + +VOIDRET upper FUNCTION((s), char *s) +{ + while (*s != '\0') { + if (islower(*s)) + *s = toupper(*s); + s++; + } +} + +char *copy FUNCTION((s), char *s) +{ + char *p; + + p = malloc((unsigned) strlen(s) + 1); + if (p == NULL) + opiefatal("Ran out of memory."); + (void) strcpy(p, s); + return (p); +} + +VOIDRET help FUNCTION((ctab, s), struct tab *ctab AND char *s) +{ + register struct tab *c; + register int width, NCMDS; + char *type; + + if (ctab == sitetab) + type = "SITE "; + else + type = ""; + width = 0, NCMDS = 0; + for (c = ctab; c->name != NULL; c++) { + int len = strlen(c->name); + + if (len > width) + width = len; + NCMDS++; + } + width = (width + 8) &~ 7; + if (s == 0) { + register int i, j, w; + int columns, lines; + + lreply(214, "The following %scommands are recognized %s.", + type, "(* =>'s unimplemented)"); + columns = 76 / width; + if (columns == 0) + columns = 1; + lines = (NCMDS + columns - 1) / columns; + for (i = 0; i < lines; i++) { + printf(" "); + for (j = 0; j < columns; j++) { + c = ctab + j * lines + i; + printf("%s%c", c->name, + c->implemented ? ' ' : '*'); + if (c + lines >= &ctab[NCMDS]) + break; + w = strlen(c->name) + 1; + while (w < width) { + putchar(' '); + w++; + } + } + printf("\r\n"); + } + (void) fflush(stdout); + return; + } + upper(s); + c = lookup(ctab, s); + if (c == (struct tab *)0) { + reply(502, "Unknown command %s.", s); + return; + } + if (c->implemented) + reply(214, "Syntax: %s%s %s", type, c->name, c->help); + else + reply(214, "%s%-*s\t%s; unimplemented.", type, width, + c->name, c->help); +} + +VOIDRET sizecmd FUNCTION((filename), char *filename) +{ + switch (type) { + case TYPE_L: + case TYPE_I: { + struct stat stbuf; + if (stat(filename, &stbuf) < 0 || + (stbuf.st_mode&S_IFMT) != S_IFREG) + reply(550, "%s: not a plain file.", filename); + else + reply(213, "%lu", stbuf.st_size); + break;} + case TYPE_A: { + FILE *fin; + register int c; + register long count; + struct stat stbuf; + fin = fopen(filename, "r"); + if (fin == NULL) { + perror_reply(550, filename); + return; + } + if (fstat(fileno(fin), &stbuf) < 0 || + (stbuf.st_mode&S_IFMT) != S_IFREG) { + reply(550, "%s: not a plain file.", filename); + (void) fclose(fin); + return; + } + + count = 0; + while((c=getc(fin)) != EOF) { + if (c == '\n') /* will get expanded to \r\n */ + count++; + count++; + } + (void) fclose(fin); + + reply(213, "%ld", count); + break;} + default: + reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]); + } +} diff --git a/contrib/opie/glob.c b/contrib/opie/glob.c new file mode 100644 index 0000000..342aa92 --- /dev/null +++ b/contrib/opie/glob.c @@ -0,0 +1,667 @@ +/* glob.c: The csh et al glob pattern matching routines. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Remove useless strings. Prototype right. + Modified at NRL for OPIE 2.0. + Originally from BSD. +*/ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * C-shell glob for random programs. + */ + +#include "opie_cfg.h" + +#if HAVE_SYS_PARAM_H +#include +#endif /* HAVE_SYS_PARAM_H */ +#include + +#include +#if HAVE_PWD_H +#include +#endif /* HAVE_PWD_H */ +#include +#include +#include +#if HAVE_LIMITS_H +#include +#endif /* HAVE_LIMITS_H */ + +#include "opie.h" + +#ifndef NCARGS +#define NCARGS 600 +#endif /* NCARGS */ +#define QUOTE 0200 +#define TRIM 0177 +#define eq(a,b) (strcmp((a),(b)) == (0)) +#define GAVSIZ (NCARGS/6) +#define isdir(d) (((d.st_mode) & S_IFMT) == S_IFDIR) + +static char **gargv; /* Pointer to the (stack) arglist */ +static int gargc; /* Number args in gargv */ +static int gnleft; +static short gflag; + +static int letter __P((register char)); +static int digit __P((register char)); +static int any __P((int, char *)); +static int blklen __P((register char **)); +VOIDRET blkfree __P((char **)); +static char *strspl __P((register char *, register char *)); + +static int tglob __P((register char c)); + +extern int errno; +static char *strend __P((char *)); + +static int globcnt; + +static char *globchars = "`{[*?"; +char *globerr = NULL; +char *home = NULL; + +static char *gpath, *gpathp, *lastgpathp; +static int globbed; +static char *entp; +static char **sortbas; + +static int amatch __P((char *p, char *s)); +static int execbrc __P((register char *p, register char *s)); +VOIDRET opiefatal __P((char *)); +char **copyblk __P((char **)); + +static int match FUNCTION((s, p), char *s AND char *p) +{ + register int c; + register char *sentp; + char sglobbed = globbed; + + if (*s == '.' && *p != '.') + return (0); + sentp = entp; + entp = s; + c = amatch(s, p); + entp = sentp; + globbed = sglobbed; + return (c); +} + + +static int Gmatch FUNCTION((s, p), register char *s AND register char *p) +{ + register int scc; + int ok, lc; + int c, cc; + + for (;;) { + scc = *s++ & TRIM; + switch (c = *p++) { + + case '[': + ok = 0; + lc = 077777; + while (cc = *p++) { + if (cc == ']') { + if (ok) + break; + return (0); + } + if (cc == '-') { + if (lc <= scc && scc <= *p++) + ok++; + } else + if (scc == (lc = cc)) + ok++; + } + if (cc == 0) + if (ok) + p--; + else + return 0; + continue; + + case '*': + if (!*p) + return (1); + for (s--; *s; s++) + if (Gmatch(s, p)) + return (1); + return (0); + + case 0: + return (scc == 0); + + default: + if ((c & TRIM) != scc) + return (0); + continue; + + case '?': + if (scc == 0) + return (0); + continue; + + } + } +} + +static VOIDRET Gcat FUNCTION((s1, s2), register char *s1 AND register char *s2) +{ + register int len = strlen(s1) + strlen(s2) + 1; + + if (len >= gnleft || gargc >= GAVSIZ - 1) + globerr = "Arguments too long"; + else { + gargc++; + gnleft -= len; + gargv[gargc] = 0; + gargv[gargc - 1] = strspl(s1, s2); + } +} + +static VOIDRET addpath FUNCTION((c), char c) +{ + + if (gpathp >= lastgpathp) + globerr = "Pathname too long"; + else { + *gpathp++ = c; + *gpathp = 0; + } +} + +static VOIDRET rscan FUNCTION((t, f), register char **t AND int (*f)__P((char))) +{ + register char *p, c; + + while (p = *t++) { + if (f == tglob) + if (*p == '~') + gflag |= 2; + else + if (eq(p, "{") || eq(p, "{}")) + continue; + while (c = *p++) + (*f) (c); + } +} + +static int tglob FUNCTION((c), register char c) +{ + if (any(c, globchars)) + gflag |= c == '{' ? 2 : 1; + return (c); +} + +static int letter FUNCTION((c), register char c) +{ + return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_'); +} + +static int digit FUNCTION((c), register char c) +{ + return (c >= '0' && c <= '9'); +} + +static int any FUNCTION((c, s), int c AND char *s) +{ + while (*s) + if (*s++ == c) + return (1); + return (0); +} + +static int blklen FUNCTION((av), register char **av) +{ + register int i = 0; + + while (*av++) + i++; + return (i); +} + +static char **blkcpy FUNCTION((oav, bv), char **oav AND register char **bv) +{ + register char **av = oav; + + while (*av++ = *bv++) + continue; + return (oav); +} + +VOIDRET blkfree FUNCTION((av0), char **av0) +{ + register char **av = av0; + + while (*av) + free(*av++); +} + +static char *strspl FUNCTION((cp, dp), register char *cp AND register char *dp) +{ + register char *ep = (char *) malloc((unsigned) (strlen(cp) + + strlen(dp) + 1)); + + if (ep == (char *) 0) + opiefatal("Out of memory"); + strcpy(ep, cp); + strcat(ep, dp); + return (ep); +} + +char **copyblk FUNCTION((v), char **v) +{ + register char **nv = (char **) malloc((unsigned) ((blklen(v) + 1) * + sizeof(char **))); + + if (nv == (char **) 0) + opiefatal("Out of memory"); + + return (blkcpy(nv, v)); +} + +static char *strend FUNCTION((cp), register char *cp) +{ + + while (*cp) + cp++; + return (cp); +} + +/* + * Extract a home directory from the password file + * The argument points to a buffer where the name of the + * user whose home directory is sought is currently. + * We write the home directory of the user back there. + */ +static int gethdir FUNCTION((home), char *home) +{ + register struct passwd *pp = getpwnam(home); + + if (!pp || home + strlen(pp->pw_dir) >= lastgpathp) + return (1); + strcpy(home, pp->pw_dir); + return (0); +} + +static VOIDRET ginit FUNCTION((agargv), char **agargv) +{ + agargv[0] = 0; + gargv = agargv; + sortbas = agargv; + gargc = 0; + gnleft = NCARGS - 4; +} + +static VOIDRET sort FUNCTION_NOARGS +{ + register char **p1, **p2, *c; + char **Gvp = &gargv[gargc]; + + p1 = sortbas; + while (p1 < Gvp - 1) { + p2 = p1; + while (++p2 < Gvp) + if (strcmp(*p1, *p2) > 0) + c = *p1, *p1 = *p2, *p2 = c; + p1++; + } + sortbas = Gvp; +} + +static VOIDRET matchdir FUNCTION((pattern), char *pattern) +{ + struct stat stb; + + register struct dirent *dp; + + DIR *dirp; + + dirp = opendir(*gpath == '\0' ? "." : gpath); + if (dirp == NULL) { + if (globbed) + return; + goto patherr2; + } +#if !defined(linux) + if (fstat(dirp->dd_fd, &stb) < 0) + goto patherr1; + if (!isdir(stb)) { + errno = ENOTDIR; + goto patherr1; + } +#endif /* !defined(linux) */ + while ((dp = readdir(dirp)) != NULL) { + if (dp->d_ino == 0) + continue; + if (match(dp->d_name, pattern)) { + Gcat(gpath, dp->d_name); + globcnt++; + } + } + closedir(dirp); + return; + +patherr1: + closedir(dirp); +patherr2: + globerr = "Bad directory components"; +} + +static VOIDRET expand FUNCTION((as), char *as) +{ + register char *cs; + register char *sgpathp, *oldcs; + struct stat stb; + + sgpathp = gpathp; + cs = as; + if (*cs == '~' && gpathp == gpath) { + addpath('~'); + for (cs++; letter(*cs) || digit(*cs) || *cs == '-';) + addpath(*cs++); + if (!*cs || *cs == '/') { + if (gpathp != gpath + 1) { + *gpathp = 0; + if (gethdir(gpath + 1)) + globerr = "Unknown user name after ~"; + strcpy(gpath, gpath + 1); + } else + strcpy(gpath, home); + gpathp = strend(gpath); + } + } + while (!any(*cs, globchars)) { + if (*cs == 0) { + if (!globbed) + Gcat(gpath, ""); + else + if (stat(gpath, &stb) >= 0) { + Gcat(gpath, ""); + globcnt++; + } + goto endit; + } + addpath(*cs++); + } + oldcs = cs; + while (cs > as && *cs != '/') + cs--, gpathp--; + if (*cs == '/') + cs++, gpathp++; + *gpathp = 0; + if (*oldcs == '{') { + execbrc(cs, ((char *) 0)); + return; + } + matchdir(cs); +endit: + gpathp = sgpathp; + *gpathp = 0; +} + +static int execbrc FUNCTION((p, s), char *p AND char *s) +{ + char restbuf[BUFSIZ + 2]; + register char *pe, *pm, *pl; + int brclev = 0; + char *lm, savec, *sgpathp; + + for (lm = restbuf; *p != '{'; *lm++ = *p++) + continue; + for (pe = ++p; *pe; pe++) + switch (*pe) { + + case '{': + brclev++; + continue; + + case '}': + if (brclev == 0) + goto pend; + brclev--; + continue; + + case '[': + for (pe++; *pe && *pe != ']'; pe++) + continue; + continue; + } +pend: + brclev = 0; + for (pl = pm = p; pm <= pe; pm++) + switch (*pm & (QUOTE | TRIM)) { + + case '{': + brclev++; + continue; + + case '}': + if (brclev) { + brclev--; + continue; + } + goto doit; + + case ',' | QUOTE: + case ',': + if (brclev) + continue; + doit: + savec = *pm; + *pm = 0; + strcpy(lm, pl); + strcat(restbuf, pe + 1); + *pm = savec; + if (s == 0) { + sgpathp = gpathp; + expand(restbuf); + gpathp = sgpathp; + *gpathp = 0; + } else + if (amatch(s, restbuf)) + return (1); + sort(); + pl = pm + 1; + if (brclev) + return (0); + continue; + + case '[': + for (pm++; *pm && *pm != ']'; pm++) + continue; + if (!*pm) + pm--; + continue; + } + if (brclev) + goto doit; + return (0); +} + +static VOIDRET acollect FUNCTION((as), register char *as) +{ + register int ogargc = gargc; + + gpathp = gpath; + *gpathp = 0; + globbed = 0; + expand(as); + if (gargc != ogargc) + sort(); +} + +static VOIDRET collect FUNCTION((as), register char *as) +{ + if (eq(as, "{") || eq(as, "{}")) { + Gcat(as, ""); + sort(); + } else + acollect(as); +} + +static int amatch FUNCTION((s, p), register char *s AND register char *p) +{ + register int scc; + int ok, lc; + char *sgpathp; + struct stat stb; + int c, cc; + + globbed = 1; + for (;;) { + scc = *s++ & TRIM; + switch (c = *p++) { + + case '{': + return (execbrc(p - 1, s - 1)); + + case '[': + ok = 0; + lc = 077777; + while (cc = *p++) { + if (cc == ']') { + if (ok) + break; + return (0); + } + if (cc == '-') { + if (lc <= scc && scc <= *p++) + ok++; + } else + if (scc == (lc = cc)) + ok++; + } + if (cc == 0) + if (ok) + p--; + else + return 0; + continue; + + case '*': + if (!*p) + return (1); + if (*p == '/') { + p++; + goto slash; + } + s--; + do { + if (amatch(s, p)) + return (1); + } + while (*s++); + return (0); + + case 0: + return (scc == 0); + + default: + if (c != scc) + return (0); + continue; + + case '?': + if (scc == 0) + return (0); + continue; + + case '/': + if (scc) + return (0); + slash: + s = entp; + sgpathp = gpathp; + while (*s) + addpath(*s++); + addpath('/'); + if (stat(gpath, &stb) == 0 && isdir(stb)) + if (*p == 0) { + Gcat(gpath, ""); + globcnt++; + } else + expand(p); + gpathp = sgpathp; + *gpathp = 0; + return (0); + } + } +} + + +char **ftpglob FUNCTION((v), register char *v) +{ + char agpath[BUFSIZ]; + char *agargv[GAVSIZ]; + char *vv[2]; + + vv[0] = v; + vv[1] = 0; + gflag = 0; + rscan(vv, tglob); + if (gflag == 0) { + vv[0] = strspl(v, ""); + return (copyblk(vv)); + } + globerr = 0; + gpath = agpath; + gpathp = gpath; + *gpathp = 0; + lastgpathp = &gpath[sizeof agpath - 2]; + ginit(agargv); + globcnt = 0; + collect(v); + if (globcnt == 0 && (gflag & 1)) { + blkfree(gargv), gargv = 0; + return (0); + } else + return (gargv = copyblk(gargv)); +} diff --git a/contrib/opie/install-sh b/contrib/opie/install-sh new file mode 100644 index 0000000..89fc9b0 --- /dev/null +++ b/contrib/opie/install-sh @@ -0,0 +1,238 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +tranformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/contrib/opie/libmissing/Makefile.in b/contrib/opie/libmissing/Makefile.in new file mode 100644 index 0000000..e00ead3 --- /dev/null +++ b/contrib/opie/libmissing/Makefile.in @@ -0,0 +1,30 @@ +## +# Makefile.in/Makefile: Directions for building libmissing. +# +# %%% copyright-cmetz +# This software is Copyright 1996 by Craig Metz, All Rights Reserved. +# The Inner Net License Version 2 applies to this software. +# You should have received a copy of the license with this software. If +# you didn't get a copy, you may request one from . +# +# History: +# +# Created by cmetz for OPIE 2.3 using old Makefiles as a guide. + +OBJS=bogus.o @MISSING@ + +CC=@CC@ +CFLAGS=$(CFL) -I.. +TARGET=libmissing.a + +all: $(TARGET) + +$(TARGET): $(OBJS) + ar r $(TARGET) $(OBJS) + @RANLIB@ $(TARGET) + +clean: + -rm -f $(OBJS) $(TARGET) + +realclean: clean + -rm -f *~ core* "\#*\#" *.o *.a Makefile diff --git a/contrib/opie/libmissing/alloca.c b/contrib/opie/libmissing/alloca.c new file mode 100644 index 0000000..61f2eeb --- /dev/null +++ b/contrib/opie/libmissing/alloca.c @@ -0,0 +1,494 @@ +/* alloca.c -- allocate automatically reclaimed memory + (Mostly) portable public-domain implementation -- D A Gwyn + + This implementation of the PWB library alloca function, + which is used to allocate space off the run-time stack so + that it is automatically reclaimed upon procedure exit, + was inspired by discussions with J. Q. Johnson of Cornell. + J.Otto Tennant contributed the Cray support. + + There are some preprocessor constants that can + be defined when compiling for your specific system, for + improved efficiency; however, the defaults should be okay. + + The general concept of this implementation is to keep + track of all alloca-allocated blocks, and reclaim any + that are found to be deeper in the stack than the current + invocation. This heuristic does not reclaim storage as + soon as it becomes invalid, but it will do so eventually. + + As a special case, alloca(0) reclaims storage without + allocating any. It is a good idea to use alloca(0) in + your main control loop, etc. to force garbage collection. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef emacs +#include "blockinput.h" +#endif + +/* If compiling with GCC 2, this file's not needed. */ +#if !defined (__GNUC__) || __GNUC__ < 2 + +/* If someone has defined alloca as a macro, + there must be some other way alloca is supposed to work. */ +#ifndef alloca + +#ifdef emacs +#ifdef static +/* actually, only want this if static is defined as "" + -- this is for usg, in which emacs must undefine static + in order to make unexec workable + */ +#ifndef STACK_DIRECTION +you +lose +-- must know STACK_DIRECTION at compile-time +#endif /* STACK_DIRECTION undefined */ +#endif /* static */ +#endif /* emacs */ + +/* If your stack is a linked list of frames, you have to + provide an "address metric" ADDRESS_FUNCTION macro. */ + +#if defined (CRAY) && defined (CRAY_STACKSEG_END) +long i00afunc (); +#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) +#else +#define ADDRESS_FUNCTION(arg) &(arg) +#endif + +#if __STDC__ +typedef void *pointer; +#else +typedef char *pointer; +#endif + +#define NULL 0 + +/* Different portions of Emacs need to call different versions of + malloc. The Emacs executable needs alloca to call xmalloc, because + ordinary malloc isn't protected from input signals. On the other + hand, the utilities in lib-src need alloca to call malloc; some of + them are very simple, and don't have an xmalloc routine. + + Non-Emacs programs expect this to call use xmalloc. + + Callers below should use malloc. */ + +#if 0 +#ifndef emacs +#define malloc xmalloc +#endif +extern pointer malloc (); +#endif /* 0 */ + +/* Define STACK_DIRECTION if you know the direction of stack + growth for your system; otherwise it will be automatically + deduced at run-time. + + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ + +#ifndef STACK_DIRECTION +#define STACK_DIRECTION 0 /* Direction unknown. */ +#endif + +#if STACK_DIRECTION != 0 + +#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ + +#else /* STACK_DIRECTION == 0; need run-time code. */ + +static int stack_dir; /* 1 or -1 once known. */ +#define STACK_DIR stack_dir + +static void +find_stack_direction () +{ + static char *addr = NULL; /* Address of first `dummy', once known. */ + auto char dummy; /* To get stack address. */ + + if (addr == NULL) + { /* Initial entry. */ + addr = ADDRESS_FUNCTION (dummy); + + find_stack_direction (); /* Recurse once. */ + } + else + { + /* Second entry. */ + if (ADDRESS_FUNCTION (dummy) > addr) + stack_dir = 1; /* Stack grew upward. */ + else + stack_dir = -1; /* Stack grew downward. */ + } +} + +#endif /* STACK_DIRECTION == 0 */ + +/* An "alloca header" is used to: + (a) chain together all alloca'ed blocks; + (b) keep track of stack depth. + + It is very important that sizeof(header) agree with malloc + alignment chunk size. The following default should work okay. */ + +#ifndef ALIGN_SIZE +#define ALIGN_SIZE sizeof(double) +#endif + +typedef union hdr +{ + char align[ALIGN_SIZE]; /* To force sizeof(header). */ + struct + { + union hdr *next; /* For chaining headers. */ + char *deep; /* For stack depth measure. */ + } h; +} header; + +static header *last_alloca_header = NULL; /* -> last alloca header. */ + +/* Return a pointer to at least SIZE bytes of storage, + which will be automatically reclaimed upon exit from + the procedure that called alloca. Originally, this space + was supposed to be taken from the current stack frame of the + caller, but that method cannot be made to work for some + implementations of C, for example under Gould's UTX/32. */ + +pointer +alloca (size) + unsigned size; +{ + auto char probe; /* Probes stack depth: */ + register char *depth = ADDRESS_FUNCTION (probe); + +#if STACK_DIRECTION == 0 + if (STACK_DIR == 0) /* Unknown growth direction. */ + find_stack_direction (); +#endif + + /* Reclaim garbage, defined as all alloca'd storage that + was allocated from deeper in the stack than currently. */ + + { + register header *hp; /* Traverses linked list. */ + +#ifdef emacs + BLOCK_INPUT; +#endif + + for (hp = last_alloca_header; hp != NULL;) + if ((STACK_DIR > 0 && hp->h.deep > depth) + || (STACK_DIR < 0 && hp->h.deep < depth)) + { + register header *np = hp->h.next; + + free ((pointer) hp); /* Collect garbage. */ + + hp = np; /* -> next header. */ + } + else + break; /* Rest are not deeper. */ + + last_alloca_header = hp; /* -> last valid storage. */ + +#ifdef emacs + UNBLOCK_INPUT; +#endif + } + + if (size == 0) + return NULL; /* No allocation required. */ + + /* Allocate combined header + user data storage. */ + + { + register pointer new = malloc (sizeof (header) + size); + /* Address of header. */ + + ((header *) new)->h.next = last_alloca_header; + ((header *) new)->h.deep = depth; + + last_alloca_header = (header *) new; + + /* User storage begins just after header. */ + + return (pointer) ((char *) new + sizeof (header)); + } +} + +#if defined (CRAY) && defined (CRAY_STACKSEG_END) + +#ifdef DEBUG_I00AFUNC +#include +#endif + +#ifndef CRAY_STACK +#define CRAY_STACK +#ifndef CRAY2 +/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ +struct stack_control_header + { + long shgrow:32; /* Number of times stack has grown. */ + long shaseg:32; /* Size of increments to stack. */ + long shhwm:32; /* High water mark of stack. */ + long shsize:32; /* Current size of stack (all segments). */ + }; + +/* The stack segment linkage control information occurs at + the high-address end of a stack segment. (The stack + grows from low addresses to high addresses.) The initial + part of the stack segment linkage control information is + 0200 (octal) words. This provides for register storage + for the routine which overflows the stack. */ + +struct stack_segment_linkage + { + long ss[0200]; /* 0200 overflow words. */ + long sssize:32; /* Number of words in this segment. */ + long ssbase:32; /* Offset to stack base. */ + long:32; + long sspseg:32; /* Offset to linkage control of previous + segment of stack. */ + long:32; + long sstcpt:32; /* Pointer to task common address block. */ + long sscsnm; /* Private control structure number for + microtasking. */ + long ssusr1; /* Reserved for user. */ + long ssusr2; /* Reserved for user. */ + long sstpid; /* Process ID for pid based multi-tasking. */ + long ssgvup; /* Pointer to multitasking thread giveup. */ + long sscray[7]; /* Reserved for Cray Research. */ + long ssa0; + long ssa1; + long ssa2; + long ssa3; + long ssa4; + long ssa5; + long ssa6; + long ssa7; + long sss0; + long sss1; + long sss2; + long sss3; + long sss4; + long sss5; + long sss6; + long sss7; + }; + +#else /* CRAY2 */ +/* The following structure defines the vector of words + returned by the STKSTAT library routine. */ +struct stk_stat + { + long now; /* Current total stack size. */ + long maxc; /* Amount of contiguous space which would + be required to satisfy the maximum + stack demand to date. */ + long high_water; /* Stack high-water mark. */ + long overflows; /* Number of stack overflow ($STKOFEN) calls. */ + long hits; /* Number of internal buffer hits. */ + long extends; /* Number of block extensions. */ + long stko_mallocs; /* Block allocations by $STKOFEN. */ + long underflows; /* Number of stack underflow calls ($STKRETN). */ + long stko_free; /* Number of deallocations by $STKRETN. */ + long stkm_free; /* Number of deallocations by $STKMRET. */ + long segments; /* Current number of stack segments. */ + long maxs; /* Maximum number of stack segments so far. */ + long pad_size; /* Stack pad size. */ + long current_address; /* Current stack segment address. */ + long current_size; /* Current stack segment size. This + number is actually corrupted by STKSTAT to + include the fifteen word trailer area. */ + long initial_address; /* Address of initial segment. */ + long initial_size; /* Size of initial segment. */ + }; + +/* The following structure describes the data structure which trails + any stack segment. I think that the description in 'asdef' is + out of date. I only describe the parts that I am sure about. */ + +struct stk_trailer + { + long this_address; /* Address of this block. */ + long this_size; /* Size of this block (does not include + this trailer). */ + long unknown2; + long unknown3; + long link; /* Address of trailer block of previous + segment. */ + long unknown5; + long unknown6; + long unknown7; + long unknown8; + long unknown9; + long unknown10; + long unknown11; + long unknown12; + long unknown13; + long unknown14; + }; + +#endif /* CRAY2 */ +#endif /* not CRAY_STACK */ + +#ifdef CRAY2 +/* Determine a "stack measure" for an arbitrary ADDRESS. + I doubt that "lint" will like this much. */ + +static long +i00afunc (long *address) +{ + struct stk_stat status; + struct stk_trailer *trailer; + long *block, size; + long result = 0; + + /* We want to iterate through all of the segments. The first + step is to get the stack status structure. We could do this + more quickly and more directly, perhaps, by referencing the + $LM00 common block, but I know that this works. */ + + STKSTAT (&status); + + /* Set up the iteration. */ + + trailer = (struct stk_trailer *) (status.current_address + + status.current_size + - 15); + + /* There must be at least one stack segment. Therefore it is + a fatal error if "trailer" is null. */ + + if (trailer == 0) + abort (); + + /* Discard segments that do not contain our argument address. */ + + while (trailer != 0) + { + block = (long *) trailer->this_address; + size = trailer->this_size; + if (block == 0 || size == 0) + abort (); + trailer = (struct stk_trailer *) trailer->link; + if ((block <= address) && (address < (block + size))) + break; + } + + /* Set the result to the offset in this segment and add the sizes + of all predecessor segments. */ + + result = address - block; + + if (trailer == 0) + { + return result; + } + + do + { + if (trailer->this_size <= 0) + abort (); + result += trailer->this_size; + trailer = (struct stk_trailer *) trailer->link; + } + while (trailer != 0); + + /* We are done. Note that if you present a bogus address (one + not in any segment), you will get a different number back, formed + from subtracting the address of the first block. This is probably + not what you want. */ + + return (result); +} + +#else /* not CRAY2 */ +/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. + Determine the number of the cell within the stack, + given the address of the cell. The purpose of this + routine is to linearize, in some sense, stack addresses + for alloca. */ + +static long +i00afunc (long address) +{ + long stkl = 0; + + long size, pseg, this_segment, stack; + long result = 0; + + struct stack_segment_linkage *ssptr; + + /* Register B67 contains the address of the end of the + current stack segment. If you (as a subprogram) store + your registers on the stack and find that you are past + the contents of B67, you have overflowed the segment. + + B67 also points to the stack segment linkage control + area, which is what we are really interested in. */ + + stkl = CRAY_STACKSEG_END (); + ssptr = (struct stack_segment_linkage *) stkl; + + /* If one subtracts 'size' from the end of the segment, + one has the address of the first word of the segment. + + If this is not the first segment, 'pseg' will be + nonzero. */ + + pseg = ssptr->sspseg; + size = ssptr->sssize; + + this_segment = stkl - size; + + /* It is possible that calling this routine itself caused + a stack overflow. Discard stack segments which do not + contain the target address. */ + + while (!(this_segment <= address && address <= stkl)) + { +#ifdef DEBUG_I00AFUNC + fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); +#endif + if (pseg == 0) + break; + stkl = stkl - pseg; + ssptr = (struct stack_segment_linkage *) stkl; + size = ssptr->sssize; + pseg = ssptr->sspseg; + this_segment = stkl - size; + } + + result = address - this_segment; + + /* If you subtract pseg from the current end of the stack, + you get the address of the previous stack segment's end. + This seems a little convoluted to me, but I'll bet you save + a cycle somewhere. */ + + while (pseg != 0) + { +#ifdef DEBUG_I00AFUNC + fprintf (stderr, "%011o %011o\n", pseg, size); +#endif + stkl = stkl - pseg; + ssptr = (struct stack_segment_linkage *) stkl; + size = ssptr->sssize; + pseg = ssptr->sspseg; + result += size; + } + return (result); +} + +#endif /* not CRAY2 */ +#endif /* CRAY */ + +#endif /* no alloca */ +#endif /* not GCC version 2 */ diff --git a/contrib/opie/libmissing/bogus.c b/contrib/opie/libmissing/bogus.c new file mode 100644 index 0000000..68dcc54 --- /dev/null +++ b/contrib/opie/libmissing/bogus.c @@ -0,0 +1 @@ +int _bogus; diff --git a/contrib/opie/libmissing/endutent.c b/contrib/opie/libmissing/endutent.c new file mode 100644 index 0000000..4a4051c --- /dev/null +++ b/contrib/opie/libmissing/endutent.c @@ -0,0 +1,18 @@ +/* endutent.c: A replacement for the endutent function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ +#include "opie_cfg.h" +#include "opie.h" + +void endutent FUNCTION_NOARGS +{ +} diff --git a/contrib/opie/libmissing/env.c b/contrib/opie/libmissing/env.c new file mode 100644 index 0000000..9a445a0 --- /dev/null +++ b/contrib/opie/libmissing/env.c @@ -0,0 +1,141 @@ +/* env.c: Replacement environment handling functions. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.2. Changed ifdefs for libmissing. + Combined all env functions and made _findenv static. + Including headers is a good idea, though. Add more headers. + Modified at NRL for OPIE 2.0. + Originally from BSD. +*/ +/* + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "opie_cfg.h" +#include +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#if HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ +#include "opie.h" + +static char *_findenv FUNCTION((name, offset), register char *name AND int *offset) +{ + extern char **environ; + register int len; + register char **P, *C; + + for (C = name, len = 0; *C && *C != '='; ++C, ++len); + for (P = environ; *P; ++P) + if (!strncmp(*P, name, len)) + if (*(C = *P + len) == '=') { + *offset = P - environ; + return (++C); + } + return (NULL); +} + +#if !HAVE_GETENV +char *getenv FUNCTION((name), char *name) +{ + int offset; + char *_findenv(); + + return (_findenv(name, &offset)); +} +#endif /* !HAVE_GETENV */ + +#if !HAVE_SETENV +int setenv FUNCTION((name, value, rewrite), char *name AND char *value AND int rewrite) +{ + extern char **environ; + static int alloced; /* if allocated space before */ + register char *C; + int l_value, offset; + + if (*value == '=') /* no `=' in value */ + ++value; + l_value = strlen(value); + if ((C = _findenv(name, &offset))) { /* find if already exists */ + if (!rewrite) + return (0); + if (strlen(C) >= l_value) { /* old larger; copy over */ + while (*C++ = *value++); + return (0); + } + } else { /* create new slot */ + register int cnt; + register char **P; + + for (P = environ, cnt = 0; *P; ++P, ++cnt); + if (alloced) { /* just increase size */ + environ = (char **) realloc((char *) environ, + (u_int) (sizeof(char *) * (cnt + 2))); + + if (!environ) + return (-1); + } else { /* get new space */ + alloced = 1; /* copy old entries into it */ + P = (char **) malloc((u_int) (sizeof(char *) * + (cnt + 2))); + + if (!P) + return (-1); + strncpy(P, environ, cnt * sizeof(char *)); + + environ = P; + } + environ[cnt + 1] = NULL; + offset = cnt; + } + for (C = name; *C && *C != '='; ++C); /* no `=' in name */ + if (!(environ[offset] = /* name + `=' + value */ + malloc((u_int) ((int) (C - name) + l_value + 2)))) + return (-1); + for (C = environ[offset]; (*C = *name++) && *C != '='; ++C); + for (*C++ = '='; *C++ = *value++;); + return (0); +} +#endif /* !HAVE_SETENV */ + +#if !HAVE_UNSETENV +VOIDRET unsetenv FUNCTION((name), char *name) +{ + extern char **environ; + register char **P; + int offset; + + while (_findenv(name, &offset)) /* if set multiple times */ + for (P = &environ[offset];; ++P) + if (!(*P = *(P + 1))) + break; +} +#endif /* !HAVE_UNSETENV */ diff --git a/contrib/opie/libmissing/getcwd.c b/contrib/opie/libmissing/getcwd.c new file mode 100644 index 0000000..30ccdc0 --- /dev/null +++ b/contrib/opie/libmissing/getcwd.c @@ -0,0 +1,23 @@ +/* getcwd.c: A replacement for the getcwd function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ +#include "opie_cfg.h" +#include "opie.h" + +char *getcwd FUNCTION((c, l), char *c AND int l) +{ +#if HAVE_GETWD + return getwd(c); +#else /* HAVE_INDEX */ +#error Need getwd() to build a replacement getcwd() +#endif /* HAVE_INDEX */ +} diff --git a/contrib/opie/libmissing/getusershell.c b/contrib/opie/libmissing/getusershell.c new file mode 100644 index 0000000..885aa04 --- /dev/null +++ b/contrib/opie/libmissing/getusershell.c @@ -0,0 +1,67 @@ +/* getusershell.c: minimal implementation of the getusershell() and + endusershell() library routines for systems that don't have them. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Modified at NRL for OPIE 2.1. Remove trailing newlines from + /etc/shells entries. Fixed infinite loop. Fixed a bug + where second invocation on would fail. + Written at NRL for OPIE 2.0. +*/ +#include "opie_cfg.h" +#include +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#include "opie.h" + +static FILE *fh = NULL; +static char *internal[] = {"/bin/sh", "/bin/csh", NULL}; +static int i = 0; +static char buffer[1024]; + +char *getusershell FUNCTION_NOARGS +{ + char *c; + + if (!fh) + fh = fopen("/etc/shells", "r"); + + if (fh) { + if (fgets(buffer, sizeof(buffer), fh)) { + if (c = strchr(buffer, '\n')) + *c = 0; + return buffer; + } else { + fclose(fh); + return NULL; + } + } else { + if (internal[i]) + return internal[i++]; + else + return NULL; + } +} + +VOIDRET endusershell FUNCTION_NOARGS +{ + if (fh) { + fclose(fh); + fh = NULL; + } + i = 0; +} diff --git a/contrib/opie/libmissing/getutline.c b/contrib/opie/libmissing/getutline.c new file mode 100644 index 0000000..9653950 --- /dev/null +++ b/contrib/opie/libmissing/getutline.c @@ -0,0 +1,50 @@ +/* getutline.c: A replacement for the getutline() function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ + +#include "opie_cfg.h" +#include +#include +#include "opie.h" + +static struct utmp u; + +struct utmp *getutline FUNCTION((utmp), struct utmp *utmp) +{ + FILE *f; + int i; + + if (!(f = __opieopen(_PATH_UTMP, 0, 0644))) + return 0; + +#if HAVE_TTYSLOT + if (i = ttyslot()) { + if (fseek(f, i * sizeof(struct utmp), SEEK_SET) < 0) + goto ret; + if (fread(&u, sizeof(struct utmp), 1, f) != sizeof(struct utmp)) + goto ret; + fclose(f); + return &u; + } +#endif /* HAVE_TTYSLOT */ + + while(fread(&u, sizeof(struct utmp), 1, f) == sizeof(struct utmp)) { + if (!strncmp(utmp->ut_line, u.ut_line, sizeof(u.ut_line) - 1)) { + fclose(f); + return &u; + } + } + +ret: + fclose(f); + return NULL; +} diff --git a/contrib/opie/libmissing/initgroups.c b/contrib/opie/libmissing/initgroups.c new file mode 100644 index 0000000..2306a0c --- /dev/null +++ b/contrib/opie/libmissing/initgroups.c @@ -0,0 +1,129 @@ +/* initgroups.c: Replacement for the initgroups() function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Modified by cmetz for OPIE 2.2. Removed useless string. + Ifdef around headers. Use FUNCTION declarations. + Not everyone has multiple groups. Work around + lack of NGROUPS. + Originally from 4.3BSD Net/2. +*/ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * initgroups + */ +#include "opie_cfg.h" + +#if HAVE_SYS_PARAM_H +#include +#endif /* HAVE_SYS_PARAM_H */ +#include +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING */ +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include + +#include "opie.h" + +struct group *getgrent(); + +int initgroups FUNCTION((uname, agroup), const char *uname AND int agroup) +{ +#if HAVE_SETGROUPS && HAVE_GETGROUPS +#if NGROUPS + int groups[NGROUPS]; +#else /* NGROUPS */ +#define STARTING_NGROUPS 32 + int groups[STARTING_NGROUPS]; +#endif /* NGROUPS */ + int ngroups; + register struct group *grp; + register int i; + + /* + * If installing primary group, duplicate it; + * the first element of groups is the effective gid + * and will be overwritten when a setgid file is executed. + */ + if (agroup >= 0) { + groups[ngroups++] = agroup; + groups[ngroups++] = agroup; + } + setgrent(); + while (grp = getgrent()) { + if (grp->gr_gid == agroup) + continue; + for (i = 0; grp->gr_mem[i]; i++) + if (!strcmp(grp->gr_mem[i], uname)) { +#if NGROUPS + if (ngroups == NGROUPS) { +#else /* NGROUPS */ + if (ngroups == STARTING_NGROUPS) { +#endif /* NGROUPS */ +fprintf(stderr, "initgroups: %s is in too many groups\n", uname); + goto toomany; + } + groups[ngroups++] = grp->gr_gid; + } + } +toomany: + endgrent(); +#if NGROUPS + if (setgroups(ngroups, groups) < 0) { + perror("setgroups"); + return (-1); + } +#else /* NGROUPS */ + ngroups++; + do { + if ((i = setgroups(--ngroups, groups) < 0) && (i != EINVAL)) { + perror("setgroups"); + return (-1); + } + } while ((i < 0) && (ngroups > 0)); +#endif /* NGROUPS */ +#endif /* HAVE_SETGROUPS && HAVE_GETGROUPS */ + return (0); +} diff --git a/contrib/opie/libmissing/memcmp.c b/contrib/opie/libmissing/memcmp.c new file mode 100644 index 0000000..e19beaf --- /dev/null +++ b/contrib/opie/libmissing/memcmp.c @@ -0,0 +1,25 @@ +/* strncasecmp.c: A replacement for the strncasecmp function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.2. +*/ +#include "opie_cfg.h" +#include "opie.h" + +int memcmp FUNCTION((s1, s2, n), unsigned char *s1 AND unsigned char *s2 AND int n) +{ + while(n--) { + if (*s1 != *s2) + return (*s1 > *s2) ? 1 : -1; + s1++; + s2++; + } + return 0; +} diff --git a/contrib/opie/libmissing/memcpy.c b/contrib/opie/libmissing/memcpy.c new file mode 100644 index 0000000..6d386c2 --- /dev/null +++ b/contrib/opie/libmissing/memcpy.c @@ -0,0 +1,25 @@ +/* memcpy.c: A replacement for the memcpy function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.2. +*/ +#include "opie_cfg.h" +#include "opie.h" + +VOIDPTR *memcpy FUNCTION((d, s, n), unsigned char *d AND unsigned char *s AND int n) +{ +#if HAVE_BCOPY + bcopy(s, d, n); +#else /* HAVE_BCOPY */ + char *d2 = d; + while(n--) (*d2++) = (*s++); +#endif /* HAVE_BCOPY */ + return d; +} diff --git a/contrib/opie/libmissing/memset.c b/contrib/opie/libmissing/memset.c new file mode 100644 index 0000000..678c441 --- /dev/null +++ b/contrib/opie/libmissing/memset.c @@ -0,0 +1,21 @@ +/* memcpy.c: A replacement for the memcpy function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.2. +*/ +#include "opie_cfg.h" +#include "opie.h" + +VOIDPTR *memset FUNCTION((d, v, n), unsigned char *d AND int v AND int n) +{ + unsigned char *d2 = d; + while(n--) (*d2++) = (unsigned char)v; + return d; +} diff --git a/contrib/opie/libmissing/pututline.c b/contrib/opie/libmissing/pututline.c new file mode 100644 index 0000000..62da458 --- /dev/null +++ b/contrib/opie/libmissing/pututline.c @@ -0,0 +1,56 @@ +/* pututline.c: A replacement for the pututline() function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ + +#include "opie_cfg.h" +#include +#include +#include "opie.h" + +void pututline FUNCTION((utmp), struct utmp *utmp) +{ + FILE *f; + struct utmp u; + int i; + + if (!(f = __opieopen(_PATH_UTMP, 1, 0644))) + return; + +#if HAVE_TTYSLOT + if (i = ttyslot()) { + if (fseek(f, i * sizeof(struct utmp), SEEK_SET) < 0) + goto ret; + fwrite(utmp, sizeof(struct utmp), 1, f); + goto ret; + } +#endif /* HAVE_TTYSLOT */ + + while(fread(&u, sizeof(struct utmp), 1, f) == sizeof(struct utmp)) { + if (!strncmp(utmp->ut_line, u.ut_line, sizeof(u.ut_line) - 1)) { + if ((i = ftell(f)) < 0) + goto ret; + if (fseek(f, i - sizeof(struct utmp), SEEK_SET) < 0) + goto ret; + fwrite(utmp, sizeof(struct utmp), 1, f); + goto ret; + } + } + + fclose(f); + + if (!(f = __opieopen(_PATH_UTMP, 2, 0644))) + return; + fwrite(utmp, sizeof(struct utmp), 1, f); + +ret: + fclose(f); +} diff --git a/contrib/opie/libmissing/sigaddset.c b/contrib/opie/libmissing/sigaddset.c new file mode 100644 index 0000000..56a613b --- /dev/null +++ b/contrib/opie/libmissing/sigaddset.c @@ -0,0 +1,36 @@ +/* sigaddset.c: A replacement for the sigaddset function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.2. +*/ + +#include "opie_cfg.h" + +#ifndef _NSIG +#ifdef NSIG +#define _NSIG NSIG +#else /* NSIG */ +#define _NSIG 32 +#endif /* NSIG */ +#endif /* _NSIG */ + +#include "opie.h" + +int sigaddset FUNCTION((set, signum), sigset_t *set AND int signum) +{ +#if sizeof(sigset_t) != sizeof(int) +Sorry, we don't currently support your system. +#else /* sizeof(sigset_t) != sizeof(int) */ + if (set && (signum > 0) && (signum < _NSIG)) + *set |= 1 << (signum - 1); +#endif /* sizeof(sigset_t) != sizeof(int) */ + + return 0; +} diff --git a/contrib/opie/libmissing/sigemptyset.c b/contrib/opie/libmissing/sigemptyset.c new file mode 100644 index 0000000..fc083f5 --- /dev/null +++ b/contrib/opie/libmissing/sigemptyset.c @@ -0,0 +1,23 @@ +/* sigemptyset.c: A replacement for the sigemptyset function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.2. +*/ + +#include "opie_cfg.h" +#include "opie.h" + +int sigemptyset FUNCTION((set), sigset_t *set) +{ + if (set) + memset(set, 0, sizeof(sigset_t)) + + return 0; +} diff --git a/contrib/opie/libmissing/sigprocmask.c b/contrib/opie/libmissing/sigprocmask.c new file mode 100644 index 0000000..4af1559 --- /dev/null +++ b/contrib/opie/libmissing/sigprocmask.c @@ -0,0 +1,68 @@ +/* sigprocmask.c: A replacement for the sigprocmask() function + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Created by cmetz for OPIE 2.2 from popen.c. Use FUNCTION + declaration et al. Include opie.h. +*/ + +#include "opie_cfg.h" + +#include +#if HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ +#if HAVE_SYS_SIGNAL_H +#include +#endif /* HAVE_SYS_SIGNAL_H */ + +#if !HAVE_SIGBLOCK || !HAVE_SIGSETMASK +Without sigblock and sigsetmask, we can't build a replacement sigprocmask. +#endif /* !HAVE_SIGBLOCK || !HAVE_SIGSETMASK */ + +#include "opie.h" + +#ifndef sigset_t +#define sigset_t int +#endif /* sigset_t */ + +int sigprocmask FUNCTION((how, set, oset), int how AND sigset_t *set AND sigset_t *oset) +{ + int old, new; + + if (set && (set != (sigset_t *)SIG_IGN) && (set != (sigset_t *)SIG_ERR)) + new = *set; + else + new = 0; + + switch(how) { + case SIG_BLOCK: + old = sigblock(new); + if (oset && (oset != (sigset_t *)SIG_IGN) && (oset != (sigset_t *)SIG_ERR)) + *oset = old; + return 0; + + case SIG_SETMASK: + old = sigsetmask(new); + if (oset && (oset != (sigset_t *)SIG_IGN) && (oset != (sigset_t *)SIG_ERR)) + *oset = old; + return 0; + + case SIG_UNBLOCK: + /* not implemented */ + default: + return 0; + } +} diff --git a/contrib/opie/libmissing/strchr.c b/contrib/opie/libmissing/strchr.c new file mode 100644 index 0000000..2903bc4 --- /dev/null +++ b/contrib/opie/libmissing/strchr.c @@ -0,0 +1,24 @@ +/* strchr.c: A replacement for the strchr function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ +#include "opie_cfg.h" +#include "opie.h" + +char *strchr FUNCTION((s, c), char *s AND int c) +{ +#if HAVE_INDEX + return index(s, c); +#else /* HAVE_INDEX */ + while(*s && (*s != c)) s++; + return *s ? s : (char *)0; +#endif /* HAVE_INDEX */ +} diff --git a/contrib/opie/libmissing/strerror.c b/contrib/opie/libmissing/strerror.c new file mode 100644 index 0000000..89632f9 --- /dev/null +++ b/contrib/opie/libmissing/strerror.c @@ -0,0 +1,34 @@ +/* strerror.c: A replacement for the strerror function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.2. +*/ + +#include "opie_cfg.h" +#include "opie.h" + +char *strerror FUNCTION((errnum), int errnum) +{ +#if HAVE_SYS_ERRLIST + extern char *sys_errlist[]; + return sys_errlist[errnum]; +#else /* NEED_STRERROR */ +#if HAVE__SYS_ERRLIST + extern char *_sys_errlist[]; + return sys_errlist[errnum]; +#else /* HAVE__SYS_ERRLIST */ + static char hexdigits[] = "0123456789abcdef"; + static char buffer[] = "System error 0x42"; + buffer[15] = hexdigits[(errnum >> 4) & 0x0f]; + buffer[16] = hexdigits[errnum & 0x0f]; + return buffer; +#endif /* HAVE__SYS_ERRLIST */ +#endif /* NEED_STRERROR */ +} diff --git a/contrib/opie/libmissing/strncasecmp.c b/contrib/opie/libmissing/strncasecmp.c new file mode 100644 index 0000000..e90b4c0 --- /dev/null +++ b/contrib/opie/libmissing/strncasecmp.c @@ -0,0 +1,30 @@ +/* strncasecmp.c: A replacement for the strncasecmp function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.2. +*/ +#include "opie_cfg.h" +#include "opie.h" + +int strncasecmp FUNCTION((s1, s2, n), unsigned char *s1 AND unsigned char *s2 AND int n) +{ + unsigned char c1, c2; + while(*s1 && *s2 && n--) { + c1 = ((*s1 >= 'A') && (*s1 <= 'Z')) ? (*s1++) + ('a' - 'A') : (*s1++); + c2 = ((*s2 >= 'A') && (*s2 <= 'Z')) ? (*s2++) + ('a' - 'A') : (*s2++); + if (c1 != c2) + return (c1 > c2) ? 1 : -1; + } + if (*s1 && !*s2) + return 1; + if (!*s1 && *s2) + return -1; + return 0; +} diff --git a/contrib/opie/libmissing/strrchr.c b/contrib/opie/libmissing/strrchr.c new file mode 100644 index 0000000..04d46ce --- /dev/null +++ b/contrib/opie/libmissing/strrchr.c @@ -0,0 +1,25 @@ +/* strrchr.c: A replacement for the strrchr function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ +#include "opie_cfg.h" +#include "opie.h" + +char *strrchr FUNCTION((s, c), char *s AND int c) +{ +#if HAVE_RINDEX + return rindex(s, c); +#else /* HAVE_RINDEX */ + char *s2 = (char *)0; + while(*s) { if (*s == c) s2 = s; s++ }; + return s2; +#endif /* HAVE_RINDEX */ +} diff --git a/contrib/opie/libmissing/sysconf.c b/contrib/opie/libmissing/sysconf.c new file mode 100644 index 0000000..fb3a5bc --- /dev/null +++ b/contrib/opie/libmissing/sysconf.c @@ -0,0 +1,30 @@ +/* sysconf.c: A (partial) replacement for the sysconf function + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ +#include "opie_cfg.h" +#if HAVE_SYS_PARAM_H +#include +#endif /* HAVE_SYS_PARAM_H */ +#include "opie.h" + +long sysconf(int name) +{ + switch(name) { + case _SC_OPEN_MAX: +#if HAVE_GETDTABLESIZE + return getdtablesize(); +#else /* HAVE_GETDTABLESIZE */ +#error Need getdtablesize() to build a replacement sysconf() +#endif /* HAVE_GETDTABLESIZE */ + + return -1; +} diff --git a/contrib/opie/libmissing/uname.c b/contrib/opie/libmissing/uname.c new file mode 100644 index 0000000..5b51fa5 --- /dev/null +++ b/contrib/opie/libmissing/uname.c @@ -0,0 +1,42 @@ +/* uname.c: A replacement for the uname function (sort of) + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Modified by cmetz for OPIE 2.3. Ifdef around gethostname(). + Created by cmetz for OPIE 2.2. +*/ +#include "opie_cfg.h" +#if HAVE_SYS_PARAM_H +#include +#endif /* HAVE_SYS_PARAM_H */ +#include "opie.h" + +int uname FUNCTION(struct utsname *buf) +{ +#if HAVE_GETHOSTNAME + char hostname[MAXHOSTNAMELEN], *c; + + memset(buf, 0, sizeof(buf)); + + if (gethostname(hostname, sizeof(hostname)-1) < 0) + return -1; + + hostname[sizeof(hostname) - 1] = 0; + + if (c = strchr(hostname, '.')) { + *c = 0; + } + + strncpy(buf->nodename, hostname, sizeof(buf->nodename) - 1); + return 0; +#else /* HAVE_GETHOSTNAME */ + strncpy(buf->nodename, "unknown", sizeof(buf->nodename) - 1); + return 0; +#endif /* HAVE_GETHOSTNAME */ +} diff --git a/contrib/opie/libopie/Makefile.in b/contrib/opie/libopie/Makefile.in new file mode 100644 index 0000000..99ab4e7 --- /dev/null +++ b/contrib/opie/libopie/Makefile.in @@ -0,0 +1,28 @@ +## +# Makefile.in/Makefile: Directions for building libopie. +# +# This software is Copyright 1996 by Craig Metz, All Rights Reserved. The Inner +# Net Copyright Notice and License Agreement version 2.00 applies to this +# software. +# +# History: +# +# Created by cmetz for OPIE 2.3 using old Makefiles as a guide. + +OBJS=md4c.o md5c.o atob8.o btoa8.o btoh.o challenge.o getsequence.o hash.o hashlen.o keycrunch.o lock.o lookup.o newseed.o parsechallenge.o passcheck.o passwd.o randomchallenge.o readpass.o unlock.o verify.o version.o btoe.o accessfile.o generator.o insecure.o getutmpentry.o readrec.o writerec.o login.o open.o + +CC=@CC@ +CFLAGS=$(CFL) -I.. +TARGET=libopie.a + +all: $(TARGET) + +$(TARGET): $(OBJS) + ar r $(TARGET) $(OBJS) + @RANLIB@ $(TARGET) + +clean: + -rm -f $(OBJS) $(TARGET) + +realclean: clean + -rm -f *~ core* "\#*\#" *.o *.a Makefile diff --git a/contrib/opie/libopie/accessfile.c b/contrib/opie/libopie/accessfile.c new file mode 100644 index 0000000..7b1866e --- /dev/null +++ b/contrib/opie/libopie/accessfile.c @@ -0,0 +1,165 @@ +/* accessfile.c: Handle trusted network access file and per-user + overrides. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Send debug info to syslog. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Ifdef around some headers. Remove extra semicolon. + Modified at NRL for OPIE 2.2. Moved from accessfile.c to + libopie/opieaccessfile.c. + Modified at NRL for OPIE 2.0. + Written at Bellcore for the S/Key Version 1 software distribution + (login.c). +*/ +#include "opie_cfg.h" + +#include +#include +#include +#include +#include +#include +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#if HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ + +#include "opie.h" + +int opieaccessfile FUNCTION((host), char *host) +{ +#ifdef PATH_ACCESS_FILE +/* Turn host into an IP address and then look it up in the authorization + * database to determine if ordinary password logins are OK + */ + long n; + struct hostent *hp; + FILE *fp; + char buf[128], **lp; + +#ifdef DEBUG + syslog(LOG_DEBUG, "accessfile: host=%s", host); +#endif /* DEBUG */ + if (!host[0]) + /* Local login, okay */ + return (1); + if (isaddr(host)) { + n = inet_addr(host); + return rdnets(n); + } else { + hp = gethostbyname(host); + if (!hp) { + printf("Unknown host %s\n", host); + return 0; + } + for (lp = hp->h_addr_list; *lp; lp++) { + memcpy((char *) &n, *lp, sizeof(n)); + if (rdnets(n)) + return (1); + } + return (0); + } +} + +int rdnets FUNCTION((host), long host) +{ + FILE *fp; + char buf[128], *cp; + long pattern, mask; + int permit_it; + + if (!(fp = fopen(PATH_ACCESS_FILE, "r"))) + return 0; + + while (fgets(buf, sizeof(buf), fp), !feof(fp)) { + if (buf[0] == '#') + continue; /* Comment */ + if (!(cp = strtok(buf, " \t"))) + continue; + /* two choices permit of deny */ + if (strncasecmp(cp, "permit", 4) == 0) { + permit_it = 1; + } else { + if (strncasecmp(cp, "deny", 4) == 0) { + permit_it = 0; + } else { + continue; /* ignore; it is not permit/deny */ + } + } + if (!(cp = strtok(NULL, " \t"))) + continue; /* Invalid line */ + pattern = inet_addr(cp); + if (!(cp = strtok(NULL, " \t"))) + continue; /* Invalid line */ + mask = inet_addr(cp); +#ifdef DEBUG + syslog(LOG_DEBUG, "accessfile: %08x & %08x == %08x (%s)", host, mask, pattern, ((host & mask) == pattern) ? "true" : "false"); +#endif /* DEBUG */ + if ((host & mask) == pattern) { + fclose(fp); + return permit_it; + } + } + fclose(fp); + return 0; +} + + +/* Return TRUE if string appears to be an IP address in dotted decimal; + * return FALSE otherwise (i.e., if string is a domain name) + */ +int isaddr FUNCTION((s), register char *s) +{ + char c; + + if (!s) + return 1; /* Can't happen */ + + while ((c = *s++) != '\0') { + if (c != '[' && c != ']' && !isdigit(c) && c != '.') + return 0; + } + return 1; +#else /* PATH_ACCESS_FILE */ + return !host[0]; +#endif /* PATH_ACCESS_FILE */ +} + +/* Returns the opposite of what you might expect */ +/* Returns 1 on error (allow)... this might not be what you want */ +int opiealways FUNCTION((homedir), char *homedir) +{ + char *opiealwayspath; + int i; + + if (!homedir) + return 1; + + if (!(opiealwayspath = malloc(strlen(homedir) + sizeof(OPIE_ALWAYS_FILE) + 1))) + return 1; + + strcpy(opiealwayspath, homedir); + strcat(opiealwayspath, "/"); + strcat(opiealwayspath, OPIE_ALWAYS_FILE); + i = access(opiealwayspath, F_OK); + free(opiealwayspath); + return (i); +} diff --git a/contrib/opie/libopie/atob8.c b/contrib/opie/libopie/atob8.c new file mode 100644 index 0000000..2c23478 --- /dev/null +++ b/contrib/opie/libopie/atob8.c @@ -0,0 +1,74 @@ +/* atob8.c: The opieatob8() library function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Return the output variable. + Don't check parameters. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Inlined and obseleted opieskipspace(). Inlined and obseleted + opiehtoi(). + Created at NRL for OPIE 2.2 from opiesubr2.c +*/ +#include "opie_cfg.h" +#include +#include "opie.h" + +/* Convert 8-byte hex-ascii string to binary array + */ +char *opieatob8 FUNCTION((out, in), char *out AND char *in) +{ + register int i; + register int val; + + for (i = 0; i < 8; i++) { + while (*in == ' ' || *in == '\t') + in++; + if (!*in) + return NULL; + + if ((*in >= '0') && (*in <= '9')) + val = *(in++) - '0'; + else + if ((*in >= 'a') && (*in <= 'f')) + val = *(in++) - 'a' + 10; + else + if ((*in >= 'A') && (*in <= 'F')) + val = *(in++) - 'A' + 10; + else + return NULL; + + *out = val << 4; + + while (*in == ' ' || *in == '\t') + in++; + if (!*in) + return NULL; + + if ((*in >= '0') && (*in <= '9')) + val = *(in++) - '0'; + else + if ((*in >= 'a') && (*in <= 'f')) + val = *(in++) - 'a' + 10; + else + if ((*in >= 'A') && (*in <= 'F')) + val = *(in++) - 'A' + 10; + else + return NULL; + + *out++ |= val; + } + + return out; +} diff --git a/contrib/opie/libopie/btoa8.c b/contrib/opie/libopie/btoa8.c new file mode 100644 index 0000000..8696a74 --- /dev/null +++ b/contrib/opie/libopie/btoa8.c @@ -0,0 +1,32 @@ +/* btoa8.c: The opiebtoa8() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3 (quick re-write). +*/ + +#include "opie_cfg.h" +#include "opie.h" + +static char hextochar[16] = +{'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + +char *opiebtoa8 FUNCTION((out, in), char *out AND char *in) +{ + int i; + char *c = out; + + for (i = 0; i < 8; i++) { + *(c++) = hextochar[((*in) >> 4) & 0x0f]; + *(c++) = hextochar[(*in++) & 0x0f]; + } + *c = 0; + + return out; +} diff --git a/contrib/opie/libopie/btoe.c b/contrib/opie/libopie/btoe.c new file mode 100644 index 0000000..e402e69 --- /dev/null +++ b/contrib/opie/libopie/btoe.c @@ -0,0 +1,2266 @@ +/* btoe: The opiebtoe() and opieetob() library functions: + Conversion to/from the six-English-word representation of a + 64 bit OTP. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Remove unnecessary address futzing with Wp in opiebtoe. + Changed unsigned long to UINT4 for Alpha. + Modified at NRL for OPIE 2.2. Moved from put.c to libopie/opiebtoe.c. + Modified at NRL for OPIE 2.0. + Written at Bellcore for the S/Key Version 1 software distribution. +*/ +#include "opie_cfg.h" +#include +#include +#include +#include +#include "opie.h" + +static UINT4 extract __P((char *s, int start, int length)); +static VOIDRET insert __P((char *s, int x, int start, int length)); +static int wsrch __P((char *w, int low, int high)); + +/* Dictionary for integer-word translations */ +static char Wp[2048][4] = +{ + "A", + "ABE", + "ACE", + "ACT", + "AD", + "ADA", + "ADD", + "AGO", + "AID", + "AIM", + "AIR", + "ALL", + "ALP", + "AM", + "AMY", + "AN", + "ANA", + "AND", + "ANN", + "ANT", + "ANY", + "APE", + "APS", + "APT", + "ARC", + "ARE", + "ARK", + "ARM", + "ART", + "AS", + "ASH", + "ASK", + "AT", + "ATE", + "AUG", + "AUK", + "AVE", + "AWE", + "AWK", + "AWL", + "AWN", + "AX", + "AYE", + "BAD", + "BAG", + "BAH", + "BAM", + "BAN", + "BAR", + "BAT", + "BAY", + "BE", + "BED", + "BEE", + "BEG", + "BEN", + "BET", + "BEY", + "BIB", + "BID", + "BIG", + "BIN", + "BIT", + "BOB", + "BOG", + "BON", + "BOO", + "BOP", + "BOW", + "BOY", + "BUB", + "BUD", + "BUG", + "BUM", + "BUN", + "BUS", + "BUT", + "BUY", + "BY", + "BYE", + "CAB", + "CAL", + "CAM", + "CAN", + "CAP", + "CAR", + "CAT", + "CAW", + "COD", + "COG", + "COL", + "CON", + "COO", + "COP", + "COT", + "COW", + "COY", + "CRY", + "CUB", + "CUE", + "CUP", + "CUR", + "CUT", + "DAB", + "DAD", + "DAM", + "DAN", + "DAR", + "DAY", + "DEE", + "DEL", + "DEN", + "DES", + "DEW", + "DID", + "DIE", + "DIG", + "DIN", + "DIP", + "DO", + "DOE", + "DOG", + "DON", + "DOT", + "DOW", + "DRY", + "DUB", + "DUD", + "DUE", + "DUG", + "DUN", + "EAR", + "EAT", + "ED", + "EEL", + "EGG", + "EGO", + "ELI", + "ELK", + "ELM", + "ELY", + "EM", + "END", + "EST", + "ETC", + "EVA", + "EVE", + "EWE", + "EYE", + "FAD", + "FAN", + "FAR", + "FAT", + "FAY", + "FED", + "FEE", + "FEW", + "FIB", + "FIG", + "FIN", + "FIR", + "FIT", + "FLO", + "FLY", + "FOE", + "FOG", + "FOR", + "FRY", + "FUM", + "FUN", + "FUR", + "GAB", + "GAD", + "GAG", + "GAL", + "GAM", + "GAP", + "GAS", + "GAY", + "GEE", + "GEL", + "GEM", + "GET", + "GIG", + "GIL", + "GIN", + "GO", + "GOT", + "GUM", + "GUN", + "GUS", + "GUT", + "GUY", + "GYM", + "GYP", + "HA", + "HAD", + "HAL", + "HAM", + "HAN", + "HAP", + "HAS", + "HAT", + "HAW", + "HAY", + "HE", + "HEM", + "HEN", + "HER", + "HEW", + "HEY", + "HI", + "HID", + "HIM", + "HIP", + "HIS", + "HIT", + "HO", + "HOB", + "HOC", + "HOE", + "HOG", + "HOP", + "HOT", + "HOW", + "HUB", + "HUE", + "HUG", + "HUH", + "HUM", + "HUT", + "I", + "ICY", + "IDA", + "IF", + "IKE", + "ILL", + "INK", + "INN", + "IO", + "ION", + "IQ", + "IRA", + "IRE", + "IRK", + "IS", + "IT", + "ITS", + "IVY", + "JAB", + "JAG", + "JAM", + "JAN", + "JAR", + "JAW", + "JAY", + "JET", + "JIG", + "JIM", + "JO", + "JOB", + "JOE", + "JOG", + "JOT", + "JOY", + "JUG", + "JUT", + "KAY", + "KEG", + "KEN", + "KEY", + "KID", + "KIM", + "KIN", + "KIT", + "LA", + "LAB", + "LAC", + "LAD", + "LAG", + "LAM", + "LAP", + "LAW", + "LAY", + "LEA", + "LED", + "LEE", + "LEG", + "LEN", + "LEO", + "LET", + "LEW", + "LID", + "LIE", + "LIN", + "LIP", + "LIT", + "LO", + "LOB", + "LOG", + "LOP", + "LOS", + "LOT", + "LOU", + "LOW", + "LOY", + "LUG", + "LYE", + "MA", + "MAC", + "MAD", + "MAE", + "MAN", + "MAO", + "MAP", + "MAT", + "MAW", + "MAY", + "ME", + "MEG", + "MEL", + "MEN", + "MET", + "MEW", + "MID", + "MIN", + "MIT", + "MOB", + "MOD", + "MOE", + "MOO", + "MOP", + "MOS", + "MOT", + "MOW", + "MUD", + "MUG", + "MUM", + "MY", + "NAB", + "NAG", + "NAN", + "NAP", + "NAT", + "NAY", + "NE", + "NED", + "NEE", + "NET", + "NEW", + "NIB", + "NIL", + "NIP", + "NIT", + "NO", + "NOB", + "NOD", + "NON", + "NOR", + "NOT", + "NOV", + "NOW", + "NU", + "NUN", + "NUT", + "O", + "OAF", + "OAK", + "OAR", + "OAT", + "ODD", + "ODE", + "OF", + "OFF", + "OFT", + "OH", + "OIL", + "OK", + "OLD", + "ON", + "ONE", + "OR", + "ORB", + "ORE", + "ORR", + "OS", + "OTT", + "OUR", + "OUT", + "OVA", + "OW", + "OWE", + "OWL", + "OWN", + "OX", + "PA", + "PAD", + "PAL", + "PAM", + "PAN", + "PAP", + "PAR", + "PAT", + "PAW", + "PAY", + "PEA", + "PEG", + "PEN", + "PEP", + "PER", + "PET", + "PEW", + "PHI", + "PI", + "PIE", + "PIN", + "PIT", + "PLY", + "PO", + "POD", + "POE", + "POP", + "POT", + "POW", + "PRO", + "PRY", + "PUB", + "PUG", + "PUN", + "PUP", + "PUT", + "QUO", + "RAG", + "RAM", + "RAN", + "RAP", + "RAT", + "RAW", + "RAY", + "REB", + "RED", + "REP", + "RET", + "RIB", + "RID", + "RIG", + "RIM", + "RIO", + "RIP", + "ROB", + "ROD", + "ROE", + "RON", + "ROT", + "ROW", + "ROY", + "RUB", + "RUE", + "RUG", + "RUM", + "RUN", + "RYE", + "SAC", + "SAD", + "SAG", + "SAL", + "SAM", + "SAN", + "SAP", + "SAT", + "SAW", + "SAY", + "SEA", + "SEC", + "SEE", + "SEN", + "SET", + "SEW", + "SHE", + "SHY", + "SIN", + "SIP", + "SIR", + "SIS", + "SIT", + "SKI", + "SKY", + "SLY", + "SO", + "SOB", + "SOD", + "SON", + "SOP", + "SOW", + "SOY", + "SPA", + "SPY", + "SUB", + "SUD", + "SUE", + "SUM", + "SUN", + "SUP", + "TAB", + "TAD", + "TAG", + "TAN", + "TAP", + "TAR", + "TEA", + "TED", + "TEE", + "TEN", + "THE", + "THY", + "TIC", + "TIE", + "TIM", + "TIN", + "TIP", + "TO", + "TOE", + "TOG", + "TOM", + "TON", + "TOO", + "TOP", + "TOW", + "TOY", + "TRY", + "TUB", + "TUG", + "TUM", + "TUN", + "TWO", + "UN", + "UP", + "US", + "USE", + "VAN", + "VAT", + "VET", + "VIE", + "WAD", + "WAG", + "WAR", + "WAS", + "WAY", + "WE", + "WEB", + "WED", + "WEE", + "WET", + "WHO", + "WHY", + "WIN", + "WIT", + "WOK", + "WON", + "WOO", + "WOW", + "WRY", + "WU", + "YAM", + "YAP", + "YAW", + "YE", + "YEA", + "YES", + "YET", + "YOU", + "ABED", + "ABEL", + "ABET", + "ABLE", + "ABUT", + "ACHE", + "ACID", + "ACME", + "ACRE", + "ACTA", + "ACTS", + "ADAM", + "ADDS", + "ADEN", + "AFAR", + "AFRO", + "AGEE", + "AHEM", + "AHOY", + "AIDA", + "AIDE", + "AIDS", + "AIRY", + "AJAR", + "AKIN", + "ALAN", + "ALEC", + "ALGA", + "ALIA", + "ALLY", + "ALMA", + "ALOE", + "ALSO", + "ALTO", + "ALUM", + "ALVA", + "AMEN", + "AMES", + "AMID", + "AMMO", + "AMOK", + "AMOS", + "AMRA", + "ANDY", + "ANEW", + "ANNA", + "ANNE", + "ANTE", + "ANTI", + "AQUA", + "ARAB", + "ARCH", + "AREA", + "ARGO", + "ARID", + "ARMY", + "ARTS", + "ARTY", + "ASIA", + "ASKS", + "ATOM", + "AUNT", + "AURA", + "AUTO", + "AVER", + "AVID", + "AVIS", + "AVON", + "AVOW", + "AWAY", + "AWRY", + "BABE", + "BABY", + "BACH", + "BACK", + "BADE", + "BAIL", + "BAIT", + "BAKE", + "BALD", + "BALE", + "BALI", + "BALK", + "BALL", + "BALM", + "BAND", + "BANE", + "BANG", + "BANK", + "BARB", + "BARD", + "BARE", + "BARK", + "BARN", + "BARR", + "BASE", + "BASH", + "BASK", + "BASS", + "BATE", + "BATH", + "BAWD", + "BAWL", + "BEAD", + "BEAK", + "BEAM", + "BEAN", + "BEAR", + "BEAT", + "BEAU", + "BECK", + "BEEF", + "BEEN", + "BEER", + "BEET", + "BELA", + "BELL", + "BELT", + "BEND", + "BENT", + "BERG", + "BERN", + "BERT", + "BESS", + "BEST", + "BETA", + "BETH", + "BHOY", + "BIAS", + "BIDE", + "BIEN", + "BILE", + "BILK", + "BILL", + "BIND", + "BING", + "BIRD", + "BITE", + "BITS", + "BLAB", + "BLAT", + "BLED", + "BLEW", + "BLOB", + "BLOC", + "BLOT", + "BLOW", + "BLUE", + "BLUM", + "BLUR", + "BOAR", + "BOAT", + "BOCA", + "BOCK", + "BODE", + "BODY", + "BOGY", + "BOHR", + "BOIL", + "BOLD", + "BOLO", + "BOLT", + "BOMB", + "BONA", + "BOND", + "BONE", + "BONG", + "BONN", + "BONY", + "BOOK", + "BOOM", + "BOON", + "BOOT", + "BORE", + "BORG", + "BORN", + "BOSE", + "BOSS", + "BOTH", + "BOUT", + "BOWL", + "BOYD", + "BRAD", + "BRAE", + "BRAG", + "BRAN", + "BRAY", + "BRED", + "BREW", + "BRIG", + "BRIM", + "BROW", + "BUCK", + "BUDD", + "BUFF", + "BULB", + "BULK", + "BULL", + "BUNK", + "BUNT", + "BUOY", + "BURG", + "BURL", + "BURN", + "BURR", + "BURT", + "BURY", + "BUSH", + "BUSS", + "BUST", + "BUSY", + "BYTE", + "CADY", + "CAFE", + "CAGE", + "CAIN", + "CAKE", + "CALF", + "CALL", + "CALM", + "CAME", + "CANE", + "CANT", + "CARD", + "CARE", + "CARL", + "CARR", + "CART", + "CASE", + "CASH", + "CASK", + "CAST", + "CAVE", + "CEIL", + "CELL", + "CENT", + "CERN", + "CHAD", + "CHAR", + "CHAT", + "CHAW", + "CHEF", + "CHEN", + "CHEW", + "CHIC", + "CHIN", + "CHOU", + "CHOW", + "CHUB", + "CHUG", + "CHUM", + "CITE", + "CITY", + "CLAD", + "CLAM", + "CLAN", + "CLAW", + "CLAY", + "CLOD", + "CLOG", + "CLOT", + "CLUB", + "CLUE", + "COAL", + "COAT", + "COCA", + "COCK", + "COCO", + "CODA", + "CODE", + "CODY", + "COED", + "COIL", + "COIN", + "COKE", + "COLA", + "COLD", + "COLT", + "COMA", + "COMB", + "COME", + "COOK", + "COOL", + "COON", + "COOT", + "CORD", + "CORE", + "CORK", + "CORN", + "COST", + "COVE", + "COWL", + "CRAB", + "CRAG", + "CRAM", + "CRAY", + "CREW", + "CRIB", + "CROW", + "CRUD", + "CUBA", + "CUBE", + "CUFF", + "CULL", + "CULT", + "CUNY", + "CURB", + "CURD", + "CURE", + "CURL", + "CURT", + "CUTS", + "DADE", + "DALE", + "DAME", + "DANA", + "DANE", + "DANG", + "DANK", + "DARE", + "DARK", + "DARN", + "DART", + "DASH", + "DATA", + "DATE", + "DAVE", + "DAVY", + "DAWN", + "DAYS", + "DEAD", + "DEAF", + "DEAL", + "DEAN", + "DEAR", + "DEBT", + "DECK", + "DEED", + "DEEM", + "DEER", + "DEFT", + "DEFY", + "DELL", + "DENT", + "DENY", + "DESK", + "DIAL", + "DICE", + "DIED", + "DIET", + "DIME", + "DINE", + "DING", + "DINT", + "DIRE", + "DIRT", + "DISC", + "DISH", + "DISK", + "DIVE", + "DOCK", + "DOES", + "DOLE", + "DOLL", + "DOLT", + "DOME", + "DONE", + "DOOM", + "DOOR", + "DORA", + "DOSE", + "DOTE", + "DOUG", + "DOUR", + "DOVE", + "DOWN", + "DRAB", + "DRAG", + "DRAM", + "DRAW", + "DREW", + "DRUB", + "DRUG", + "DRUM", + "DUAL", + "DUCK", + "DUCT", + "DUEL", + "DUET", + "DUKE", + "DULL", + "DUMB", + "DUNE", + "DUNK", + "DUSK", + "DUST", + "DUTY", + "EACH", + "EARL", + "EARN", + "EASE", + "EAST", + "EASY", + "EBEN", + "ECHO", + "EDDY", + "EDEN", + "EDGE", + "EDGY", + "EDIT", + "EDNA", + "EGAN", + "ELAN", + "ELBA", + "ELLA", + "ELSE", + "EMIL", + "EMIT", + "EMMA", + "ENDS", + "ERIC", + "EROS", + "EVEN", + "EVER", + "EVIL", + "EYED", + "FACE", + "FACT", + "FADE", + "FAIL", + "FAIN", + "FAIR", + "FAKE", + "FALL", + "FAME", + "FANG", + "FARM", + "FAST", + "FATE", + "FAWN", + "FEAR", + "FEAT", + "FEED", + "FEEL", + "FEET", + "FELL", + "FELT", + "FEND", + "FERN", + "FEST", + "FEUD", + "FIEF", + "FIGS", + "FILE", + "FILL", + "FILM", + "FIND", + "FINE", + "FINK", + "FIRE", + "FIRM", + "FISH", + "FISK", + "FIST", + "FITS", + "FIVE", + "FLAG", + "FLAK", + "FLAM", + "FLAT", + "FLAW", + "FLEA", + "FLED", + "FLEW", + "FLIT", + "FLOC", + "FLOG", + "FLOW", + "FLUB", + "FLUE", + "FOAL", + "FOAM", + "FOGY", + "FOIL", + "FOLD", + "FOLK", + "FOND", + "FONT", + "FOOD", + "FOOL", + "FOOT", + "FORD", + "FORE", + "FORK", + "FORM", + "FORT", + "FOSS", + "FOUL", + "FOUR", + "FOWL", + "FRAU", + "FRAY", + "FRED", + "FREE", + "FRET", + "FREY", + "FROG", + "FROM", + "FUEL", + "FULL", + "FUME", + "FUND", + "FUNK", + "FURY", + "FUSE", + "FUSS", + "GAFF", + "GAGE", + "GAIL", + "GAIN", + "GAIT", + "GALA", + "GALE", + "GALL", + "GALT", + "GAME", + "GANG", + "GARB", + "GARY", + "GASH", + "GATE", + "GAUL", + "GAUR", + "GAVE", + "GAWK", + "GEAR", + "GELD", + "GENE", + "GENT", + "GERM", + "GETS", + "GIBE", + "GIFT", + "GILD", + "GILL", + "GILT", + "GINA", + "GIRD", + "GIRL", + "GIST", + "GIVE", + "GLAD", + "GLEE", + "GLEN", + "GLIB", + "GLOB", + "GLOM", + "GLOW", + "GLUE", + "GLUM", + "GLUT", + "GOAD", + "GOAL", + "GOAT", + "GOER", + "GOES", + "GOLD", + "GOLF", + "GONE", + "GONG", + "GOOD", + "GOOF", + "GORE", + "GORY", + "GOSH", + "GOUT", + "GOWN", + "GRAB", + "GRAD", + "GRAY", + "GREG", + "GREW", + "GREY", + "GRID", + "GRIM", + "GRIN", + "GRIT", + "GROW", + "GRUB", + "GULF", + "GULL", + "GUNK", + "GURU", + "GUSH", + "GUST", + "GWEN", + "GWYN", + "HAAG", + "HAAS", + "HACK", + "HAIL", + "HAIR", + "HALE", + "HALF", + "HALL", + "HALO", + "HALT", + "HAND", + "HANG", + "HANK", + "HANS", + "HARD", + "HARK", + "HARM", + "HART", + "HASH", + "HAST", + "HATE", + "HATH", + "HAUL", + "HAVE", + "HAWK", + "HAYS", + "HEAD", + "HEAL", + "HEAR", + "HEAT", + "HEBE", + "HECK", + "HEED", + "HEEL", + "HEFT", + "HELD", + "HELL", + "HELM", + "HERB", + "HERD", + "HERE", + "HERO", + "HERS", + "HESS", + "HEWN", + "HICK", + "HIDE", + "HIGH", + "HIKE", + "HILL", + "HILT", + "HIND", + "HINT", + "HIRE", + "HISS", + "HIVE", + "HOBO", + "HOCK", + "HOFF", + "HOLD", + "HOLE", + "HOLM", + "HOLT", + "HOME", + "HONE", + "HONK", + "HOOD", + "HOOF", + "HOOK", + "HOOT", + "HORN", + "HOSE", + "HOST", + "HOUR", + "HOVE", + "HOWE", + "HOWL", + "HOYT", + "HUCK", + "HUED", + "HUFF", + "HUGE", + "HUGH", + "HUGO", + "HULK", + "HULL", + "HUNK", + "HUNT", + "HURD", + "HURL", + "HURT", + "HUSH", + "HYDE", + "HYMN", + "IBIS", + "ICON", + "IDEA", + "IDLE", + "IFFY", + "INCA", + "INCH", + "INTO", + "IONS", + "IOTA", + "IOWA", + "IRIS", + "IRMA", + "IRON", + "ISLE", + "ITCH", + "ITEM", + "IVAN", + "JACK", + "JADE", + "JAIL", + "JAKE", + "JANE", + "JAVA", + "JEAN", + "JEFF", + "JERK", + "JESS", + "JEST", + "JIBE", + "JILL", + "JILT", + "JIVE", + "JOAN", + "JOBS", + "JOCK", + "JOEL", + "JOEY", + "JOHN", + "JOIN", + "JOKE", + "JOLT", + "JOVE", + "JUDD", + "JUDE", + "JUDO", + "JUDY", + "JUJU", + "JUKE", + "JULY", + "JUNE", + "JUNK", + "JUNO", + "JURY", + "JUST", + "JUTE", + "KAHN", + "KALE", + "KANE", + "KANT", + "KARL", + "KATE", + "KEEL", + "KEEN", + "KENO", + "KENT", + "KERN", + "KERR", + "KEYS", + "KICK", + "KILL", + "KIND", + "KING", + "KIRK", + "KISS", + "KITE", + "KLAN", + "KNEE", + "KNEW", + "KNIT", + "KNOB", + "KNOT", + "KNOW", + "KOCH", + "KONG", + "KUDO", + "KURD", + "KURT", + "KYLE", + "LACE", + "LACK", + "LACY", + "LADY", + "LAID", + "LAIN", + "LAIR", + "LAKE", + "LAMB", + "LAME", + "LAND", + "LANE", + "LANG", + "LARD", + "LARK", + "LASS", + "LAST", + "LATE", + "LAUD", + "LAVA", + "LAWN", + "LAWS", + "LAYS", + "LEAD", + "LEAF", + "LEAK", + "LEAN", + "LEAR", + "LEEK", + "LEER", + "LEFT", + "LEND", + "LENS", + "LENT", + "LEON", + "LESK", + "LESS", + "LEST", + "LETS", + "LIAR", + "LICE", + "LICK", + "LIED", + "LIEN", + "LIES", + "LIEU", + "LIFE", + "LIFT", + "LIKE", + "LILA", + "LILT", + "LILY", + "LIMA", + "LIMB", + "LIME", + "LIND", + "LINE", + "LINK", + "LINT", + "LION", + "LISA", + "LIST", + "LIVE", + "LOAD", + "LOAF", + "LOAM", + "LOAN", + "LOCK", + "LOFT", + "LOGE", + "LOIS", + "LOLA", + "LONE", + "LONG", + "LOOK", + "LOON", + "LOOT", + "LORD", + "LORE", + "LOSE", + "LOSS", + "LOST", + "LOUD", + "LOVE", + "LOWE", + "LUCK", + "LUCY", + "LUGE", + "LUKE", + "LULU", + "LUND", + "LUNG", + "LURA", + "LURE", + "LURK", + "LUSH", + "LUST", + "LYLE", + "LYNN", + "LYON", + "LYRA", + "MACE", + "MADE", + "MAGI", + "MAID", + "MAIL", + "MAIN", + "MAKE", + "MALE", + "MALI", + "MALL", + "MALT", + "MANA", + "MANN", + "MANY", + "MARC", + "MARE", + "MARK", + "MARS", + "MART", + "MARY", + "MASH", + "MASK", + "MASS", + "MAST", + "MATE", + "MATH", + "MAUL", + "MAYO", + "MEAD", + "MEAL", + "MEAN", + "MEAT", + "MEEK", + "MEET", + "MELD", + "MELT", + "MEMO", + "MEND", + "MENU", + "MERT", + "MESH", + "MESS", + "MICE", + "MIKE", + "MILD", + "MILE", + "MILK", + "MILL", + "MILT", + "MIMI", + "MIND", + "MINE", + "MINI", + "MINK", + "MINT", + "MIRE", + "MISS", + "MIST", + "MITE", + "MITT", + "MOAN", + "MOAT", + "MOCK", + "MODE", + "MOLD", + "MOLE", + "MOLL", + "MOLT", + "MONA", + "MONK", + "MONT", + "MOOD", + "MOON", + "MOOR", + "MOOT", + "MORE", + "MORN", + "MORT", + "MOSS", + "MOST", + "MOTH", + "MOVE", + "MUCH", + "MUCK", + "MUDD", + "MUFF", + "MULE", + "MULL", + "MURK", + "MUSH", + "MUST", + "MUTE", + "MUTT", + "MYRA", + "MYTH", + "NAGY", + "NAIL", + "NAIR", + "NAME", + "NARY", + "NASH", + "NAVE", + "NAVY", + "NEAL", + "NEAR", + "NEAT", + "NECK", + "NEED", + "NEIL", + "NELL", + "NEON", + "NERO", + "NESS", + "NEST", + "NEWS", + "NEWT", + "NIBS", + "NICE", + "NICK", + "NILE", + "NINA", + "NINE", + "NOAH", + "NODE", + "NOEL", + "NOLL", + "NONE", + "NOOK", + "NOON", + "NORM", + "NOSE", + "NOTE", + "NOUN", + "NOVA", + "NUDE", + "NULL", + "NUMB", + "OATH", + "OBEY", + "OBOE", + "ODIN", + "OHIO", + "OILY", + "OINT", + "OKAY", + "OLAF", + "OLDY", + "OLGA", + "OLIN", + "OMAN", + "OMEN", + "OMIT", + "ONCE", + "ONES", + "ONLY", + "ONTO", + "ONUS", + "ORAL", + "ORGY", + "OSLO", + "OTIS", + "OTTO", + "OUCH", + "OUST", + "OUTS", + "OVAL", + "OVEN", + "OVER", + "OWLY", + "OWNS", + "QUAD", + "QUIT", + "QUOD", + "RACE", + "RACK", + "RACY", + "RAFT", + "RAGE", + "RAID", + "RAIL", + "RAIN", + "RAKE", + "RANK", + "RANT", + "RARE", + "RASH", + "RATE", + "RAVE", + "RAYS", + "READ", + "REAL", + "REAM", + "REAR", + "RECK", + "REED", + "REEF", + "REEK", + "REEL", + "REID", + "REIN", + "RENA", + "REND", + "RENT", + "REST", + "RICE", + "RICH", + "RICK", + "RIDE", + "RIFT", + "RILL", + "RIME", + "RING", + "RINK", + "RISE", + "RISK", + "RITE", + "ROAD", + "ROAM", + "ROAR", + "ROBE", + "ROCK", + "RODE", + "ROIL", + "ROLL", + "ROME", + "ROOD", + "ROOF", + "ROOK", + "ROOM", + "ROOT", + "ROSA", + "ROSE", + "ROSS", + "ROSY", + "ROTH", + "ROUT", + "ROVE", + "ROWE", + "ROWS", + "RUBE", + "RUBY", + "RUDE", + "RUDY", + "RUIN", + "RULE", + "RUNG", + "RUNS", + "RUNT", + "RUSE", + "RUSH", + "RUSK", + "RUSS", + "RUST", + "RUTH", + "SACK", + "SAFE", + "SAGE", + "SAID", + "SAIL", + "SALE", + "SALK", + "SALT", + "SAME", + "SAND", + "SANE", + "SANG", + "SANK", + "SARA", + "SAUL", + "SAVE", + "SAYS", + "SCAN", + "SCAR", + "SCAT", + "SCOT", + "SEAL", + "SEAM", + "SEAR", + "SEAT", + "SEED", + "SEEK", + "SEEM", + "SEEN", + "SEES", + "SELF", + "SELL", + "SEND", + "SENT", + "SETS", + "SEWN", + "SHAG", + "SHAM", + "SHAW", + "SHAY", + "SHED", + "SHIM", + "SHIN", + "SHOD", + "SHOE", + "SHOT", + "SHOW", + "SHUN", + "SHUT", + "SICK", + "SIDE", + "SIFT", + "SIGH", + "SIGN", + "SILK", + "SILL", + "SILO", + "SILT", + "SINE", + "SING", + "SINK", + "SIRE", + "SITE", + "SITS", + "SITU", + "SKAT", + "SKEW", + "SKID", + "SKIM", + "SKIN", + "SKIT", + "SLAB", + "SLAM", + "SLAT", + "SLAY", + "SLED", + "SLEW", + "SLID", + "SLIM", + "SLIT", + "SLOB", + "SLOG", + "SLOT", + "SLOW", + "SLUG", + "SLUM", + "SLUR", + "SMOG", + "SMUG", + "SNAG", + "SNOB", + "SNOW", + "SNUB", + "SNUG", + "SOAK", + "SOAR", + "SOCK", + "SODA", + "SOFA", + "SOFT", + "SOIL", + "SOLD", + "SOME", + "SONG", + "SOON", + "SOOT", + "SORE", + "SORT", + "SOUL", + "SOUR", + "SOWN", + "STAB", + "STAG", + "STAN", + "STAR", + "STAY", + "STEM", + "STEW", + "STIR", + "STOW", + "STUB", + "STUN", + "SUCH", + "SUDS", + "SUIT", + "SULK", + "SUMS", + "SUNG", + "SUNK", + "SURE", + "SURF", + "SWAB", + "SWAG", + "SWAM", + "SWAN", + "SWAT", + "SWAY", + "SWIM", + "SWUM", + "TACK", + "TACT", + "TAIL", + "TAKE", + "TALE", + "TALK", + "TALL", + "TANK", + "TASK", + "TATE", + "TAUT", + "TEAL", + "TEAM", + "TEAR", + "TECH", + "TEEM", + "TEEN", + "TEET", + "TELL", + "TEND", + "TENT", + "TERM", + "TERN", + "TESS", + "TEST", + "THAN", + "THAT", + "THEE", + "THEM", + "THEN", + "THEY", + "THIN", + "THIS", + "THUD", + "THUG", + "TICK", + "TIDE", + "TIDY", + "TIED", + "TIER", + "TILE", + "TILL", + "TILT", + "TIME", + "TINA", + "TINE", + "TINT", + "TINY", + "TIRE", + "TOAD", + "TOGO", + "TOIL", + "TOLD", + "TOLL", + "TONE", + "TONG", + "TONY", + "TOOK", + "TOOL", + "TOOT", + "TORE", + "TORN", + "TOTE", + "TOUR", + "TOUT", + "TOWN", + "TRAG", + "TRAM", + "TRAY", + "TREE", + "TREK", + "TRIG", + "TRIM", + "TRIO", + "TROD", + "TROT", + "TROY", + "TRUE", + "TUBA", + "TUBE", + "TUCK", + "TUFT", + "TUNA", + "TUNE", + "TUNG", + "TURF", + "TURN", + "TUSK", + "TWIG", + "TWIN", + "TWIT", + "ULAN", + "UNIT", + "URGE", + "USED", + "USER", + "USES", + "UTAH", + "VAIL", + "VAIN", + "VALE", + "VARY", + "VASE", + "VAST", + "VEAL", + "VEDA", + "VEIL", + "VEIN", + "VEND", + "VENT", + "VERB", + "VERY", + "VETO", + "VICE", + "VIEW", + "VINE", + "VISE", + "VOID", + "VOLT", + "VOTE", + "WACK", + "WADE", + "WAGE", + "WAIL", + "WAIT", + "WAKE", + "WALE", + "WALK", + "WALL", + "WALT", + "WAND", + "WANE", + "WANG", + "WANT", + "WARD", + "WARM", + "WARN", + "WART", + "WASH", + "WAST", + "WATS", + "WATT", + "WAVE", + "WAVY", + "WAYS", + "WEAK", + "WEAL", + "WEAN", + "WEAR", + "WEED", + "WEEK", + "WEIR", + "WELD", + "WELL", + "WELT", + "WENT", + "WERE", + "WERT", + "WEST", + "WHAM", + "WHAT", + "WHEE", + "WHEN", + "WHET", + "WHOA", + "WHOM", + "WICK", + "WIFE", + "WILD", + "WILL", + "WIND", + "WINE", + "WING", + "WINK", + "WINO", + "WIRE", + "WISE", + "WISH", + "WITH", + "WOLF", + "WONT", + "WOOD", + "WOOL", + "WORD", + "WORE", + "WORK", + "WORM", + "WORN", + "WOVE", + "WRIT", + "WYNN", + "YALE", + "YANG", + "YANK", + "YARD", + "YARN", + "YAWL", + "YAWN", + "YEAH", + "YEAR", + "YELL", + "YOGA", + "YOKE" +}; + +/* Encode 8 bytes in 'c' as a string of English words. */ +char *opiebtoe FUNCTION((engout, c), char *engout AND char *c) +{ + char cp[9]; /* add in room for the parity 2 bits */ + int p, i; + + engout[0] = '\0'; + memcpy(cp, c, 8); + /* compute parity */ + for (p = 0, i = 0; i < 64; i += 2) + p += extract(cp, i, 2); + + cp[8] = (char)(p << 6); + strncat(engout, Wp[extract(cp, 0, 11)], 4); + strcat(engout, " "); + strncat(engout, Wp[extract(cp, 11, 11)], 4); + strcat(engout, " "); + strncat(engout, Wp[extract(cp, 22, 11)], 4); + strcat(engout, " "); + strncat(engout, Wp[extract(cp, 33, 11)], 4); + strcat(engout, " "); + strncat(engout, Wp[extract(cp, 44, 11)], 4); + strcat(engout, " "); + strncat(engout, Wp[extract(cp, 55, 11)], 4); + return (engout); +} + +/* convert English to binary + * returns 1 OK - all good words and parity is OK + * 0 word not in data base + * -1 badly formed in put ie > 4 char word + * -2 words OK but parity is wrong + */ +int opieetob FUNCTION((out, e), char *out AND char *e) +{ + char *word, *c, *input, b[9]; + int i, p, v, l, low, high, rval = -1; + + if (e == NULL) + return -1; + + if ((i = strlen(e)) > 64) + i = 64; + + if (!(input = malloc(i+1))) + return -1; + + strncpy(input, e, i); + input[i] = 0; + memset(b, 0, sizeof(b)); + memset(out, 0, 8); + + for (i = 0, p = 0, word = c = input; i < 6; i++, p += 11) { + while (*c && !isalpha(*c)) c++; + word = c; + while (*c) { + if (islower(*c)) + *c = toupper(*c); + if (*c == '1') + *c = 'L'; + if (*c == '0') + *c = 'O'; + if (*c == '5') + *c = 'S'; + if (!isalpha(*c)) + break; + c++; + } + if ((!*c) && (i != 5)) + goto opiebtoeret; + *c = 0; + c++; + if (c == word) + goto opiebtoeret; + l = strlen(word); + if (l > 4 || l < 1) + goto opiebtoeret; + if (l < 4) { + low = 0; + high = 570; + } else { + low = 571; + high = 2047; + } + if ((v = wsrch(word, low, high)) < 0) { + rval = 0; + goto opiebtoeret; + } + insert(b, v, p, 11); + } + + /* now check the parity of what we got */ + for (p = 0, i = 0; i < 64; i += 2) + p += extract(b, i, 2); + + if ((p & 3) != extract(b, 64, 2)) { + rval = -2; + goto opiebtoeret; + } + + memcpy(out, b, 8); + + rval = 1; + +opiebtoeret: + free(input); + return rval; +} + +/* Internal subroutines for word encoding/decoding */ + +/* Dictionary binary search */ +static int wsrch FUNCTION((w, low, high), char *w AND int low AND int high) +{ + int i, j; + + for (;;) { + i = (low + high) / 2; + if ((j = strncmp(w, Wp[i], 4)) == 0) + return i; /* Found it */ + if (high == low + 1) { + /* Avoid effects of integer truncation in /2 */ + if (strncmp(w, Wp[high], 4) == 0) + return high; + else + return -1; + } + if (low >= high) + return -1; /* I don't *think* this can happen... */ + if (j < 0) + high = i; /* Search lower half */ + else + low = i; /* Search upper half */ + } +} + +static VOIDRET insert FUNCTION((s, x, start, length), char *s AND int x AND int start AND int length) +{ + unsigned char cl; + unsigned char cc; + unsigned char cr; + UINT4 y; + int shift; + + shift = ((8 - ((start + length) % 8)) % 8); + y = (long) x << shift; + cl = (y >> 16) & 0xff; + cc = (y >> 8) & 0xff; + cr = y & 0xff; + if (shift + length > 16) { + s[start / 8] |= cl; + s[start / 8 + 1] |= cc; + s[start / 8 + 2] |= cr; + } else + if (shift + length > 8) { + s[start / 8] |= cc; + s[start / 8 + 1] |= cr; + } else { + s[start / 8] |= cr; + } +} + +static UINT4 extract FUNCTION((s, start, length), char *s AND int start AND int length) +{ + UINT4 x; + unsigned char cl; + unsigned char cc; + unsigned char cr; + + cl = s[start / 8]; + cc = s[start / 8 + 1]; + cr = s[start / 8 + 2]; + x = ((UINT4) (cl << 8 | cc) << 8 | cr); + x = x >> (24 - (length + (start % 8))); + x = (x & (0xffff >> (16 - length))); + return (x); +} diff --git a/contrib/opie/libopie/btoh.c b/contrib/opie/libopie/btoh.c new file mode 100644 index 0000000..68cf75f --- /dev/null +++ b/contrib/opie/libopie/btoh.c @@ -0,0 +1,35 @@ +/* btoh.c: The opiebtoh() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ + +#include "opie_cfg.h" +#include "opie.h" + +static char hextochar[16] = +{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + +char *opiebtoh FUNCTION((out, in), char *out AND char *in) +{ + int i; + char *c = out; + + for (i = 0; i < 4; i++) { + *(c++) = hextochar[((*in) >> 4) & 0x0f]; + *(c++) = hextochar[(*in++) & 0x0f]; + *(c++) = hextochar[((*in) >> 4) & 0x0f]; + *(c++) = hextochar[(*in++) & 0x0f]; + *(c++) = ' '; + } + *(--c) = 0; + + return out; +} diff --git a/contrib/opie/libopie/challenge.c b/contrib/opie/libopie/challenge.c new file mode 100644 index 0000000..d67d495 --- /dev/null +++ b/contrib/opie/libopie/challenge.c @@ -0,0 +1,74 @@ +/* challenge.c: The opiechallenge() library function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Use opie_ prefix. Send debug info to + syslog. Add sha plumbing. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Created at NRL for OPIE 2.2 from opiesubr2.c +*/ +#include "opie_cfg.h" +#include +#include +#if DEBUG +#include +#endif /* DEBUG */ +#include "opie.h" + +/* Return an OTP challenge string for user 'name'. + + The return values are: + + 0 = All good + -1 = Low-level error (file, memory, I/O, etc.) + 1 = High-level error (user not found or locked) + + This function MUST eventually be followed by an opieverify() to release + the user lock and file handles. + + This function will give you a blanked-out state block if it returns a + nonzero status. Even though it returns a non-zero status and a blank + state block, you still MUST call opieverify() to clear the lock and + any internal state (the latter condition is not actually used yet). +*/ + +static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" }; + +int opiechallenge FUNCTION((mp, name, ss), struct opie *mp AND char *name AND char *ss) +{ + int rval = -1; + + memset(mp, 0, sizeof(*mp)); + + rval = opielookup(mp, name); +#if DEBUG + if (rval) syslog(LOG_DEBUG, "opiechallenge: opielookup(mp, name=%s) returned %d", name, rval); +#endif /* DEBUG */ + + if (!rval) { + rval = opielock(name); +#if DEBUG + if (rval) syslog(LOG_DEBUG, "opiechallenge: opielock(name=%s) returned %d", name, rval); +#endif /* DEBUG */ + } + + if (rval) { + opierandomchallenge(ss); + memset(mp, 0, sizeof(*mp)); + } else + sprintf(ss, "otp-%s %d %s", algids[MDX], mp->opie_n - 1, mp->opie_seed); + + return rval; +} diff --git a/contrib/opie/libopie/generator.c b/contrib/opie/libopie/generator.c new file mode 100644 index 0000000..ccd67c7 --- /dev/null +++ b/contrib/opie/libopie/generator.c @@ -0,0 +1,110 @@ +/* generator.c: The opiegenerator() library function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Modified by cmetz for OPIE 2.3. Use _opieparsechallenge(). ifdef + around string.h. Output hex responses by default, output + OTP re-init extended responses (same secret) if sequence + number falls below 10. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Bug fixes. + Created at NRL for OPIE 2.2. +*/ + +#include "opie_cfg.h" +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#include "opie.h" + +static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" }; + +int opiegenerator FUNCTION((buffer, secret, response), char *buffer AND char *secret AND char *response) +{ + int algorithm; + int sequence; + char *seed; + char key[8]; + int i; + + if (!(buffer = strstr(buffer, "otp-"))) + return 1; + + buffer += 4; + + if (_opieparsechallenge(buffer, &algorithm, &sequence, &seed)) + return 1; + + if ((sequence < 2) || (sequence > 9999)) + return 1; + + if (opiepasscheck(secret)) + return -2; + + if (i = opiekeycrunch(algorithm, key, seed, secret)) + return i; + + if (sequence < 10) { + char newseed[OPIE_SEED_MAX + 1]; + char newkey[8], cko[8], ckn[8], ckxor[8], cv[8]; + char *c; + char buf[OPIE_SEED_MAX + 48 + 1]; + + if (opienewseed(strcpy(newseed, seed)) < 0) + return -1; + + if (opiekeycrunch(algorithm, newkey, newseed, secret)) + return -1; + + for (i = 0; i < 499; i++) + opiehash(newkey, algorithm); + + if (opiekeycrunch(algorithm | 0x10, cko, seed, secret)) + return -1; + + if (opiekeycrunch(algorithm | 0x10, ckn, newseed, secret)) + return -1; + + for (i = 0; i < 8; i++) + ckxor[i] = cko[i] ^ ckn[i]; + + strcpy(response, "init:"); + strcat(response, opiebtoh(buf, key)); + sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed); + strcat(response, buf); + strcat(response, opiebtoh(buf, newkey)); + strcat(response, ":"); + strcat(response, opiebtoh(buf, ckxor)); + strcat(response, ":"); + + c = buf; + memcpy(c, ckn, sizeof(ckn)); c += sizeof(ckn); + memcpy(c, key, sizeof(key)); c += sizeof(key); +#ifdef HAVE_ANSISPRINTF + c += sprintf(c, "%s 499 %s", algids[algorithm], newseed); +#else /* HAVE_ANSISPRINTF */ + sprintf(c, "%s 499 %s", algids[algorithm], newseed); + while(*c) c++; +#endif /* HAVE_ANSISPRINTF */ + memcpy(c, newkey, sizeof(newkey)); c += sizeof(newkey); + memcpy(c, ckxor, sizeof(ckxor)); c += sizeof(ckxor); + memcpy(c, ckn, sizeof(ckn)); c += sizeof(ckn); + opiehashlen(algorithm, buf, cv, (unsigned int)c - (unsigned int)buf); + + strcat(response, opiebtoh(buf, cv)); + } else { + while (sequence-- != 0) + opiehash(key, algorithm); + + opiebtoh(response, key); + } + + return 0; +} diff --git a/contrib/opie/libopie/getsequence.c b/contrib/opie/libopie/getsequence.c new file mode 100644 index 0000000..f0a6e78 --- /dev/null +++ b/contrib/opie/libopie/getsequence.c @@ -0,0 +1,27 @@ +/* getsequence.c: The opiegetsequence() library function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Use opie_ prefix. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Created at NRL for OPIE 2.2 from opiesubr2.c +*/ +#include "opie_cfg.h" +#include "opie.h" + +int opiegetsequence FUNCTION((stateblock), struct opie *stateblock) +{ + return stateblock->opie_n; +} diff --git a/contrib/opie/libopie/getutmpentry.c b/contrib/opie/libopie/getutmpentry.c new file mode 100644 index 0000000..8013f87 --- /dev/null +++ b/contrib/opie/libopie/getutmpentry.c @@ -0,0 +1,72 @@ +/* getutmpentry.c: The __opiegetutmpentry() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3 (re-write). +*/ + +#include "opie_cfg.h" +#include +#include +#include + +#if DOUTMPX +#include +#define getutline(x) getutxline(x) +#define utmp utmpx +#endif /* DOUTMPX */ + +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ + +#if DEBUG +#include +#endif /* DEBUG */ +#include "opie.h" + +#if !HAVE_GETUTLINE +struct utmp *getutline __P((struct utmp *)); +#endif /* HAVE_GETUTLINE */ + +int __opiegetutmpentry FUNCTION((line, utmp), char *line AND struct utmp *utmp) +{ + struct utmp u, *pu; + + memset(&u, 0, sizeof(u)); + + if (!strncmp(line, "/dev/", 5)) { + strncpy(u.ut_line, line + 5, sizeof(u.ut_line)); + if ((pu = getutline(&u))) + goto gotit; + +#ifdef hpux + strcpy(u.ut_line, "pty/"); + strncpy(u.ut_line + 4, line + 5, sizeof(u.ut_line) - 4); + if ((pu = getutline(&u))) + goto gotit; +#endif /* hpux */ + } + + strncpy(u.ut_line, line, sizeof(u.ut_line)); + if ((pu = getutline(&u))) + goto gotit; + +#if DEBUG + syslog(LOG_DEBUG, "__opiegetutmpentry: failed to find entry for line %s", line); +#endif /* DEBUG */ + return -1; + +gotit: +#if DEBUG + syslog(LOG_DEBUG, "__opiegetutmpentry: succeeded with line %s", pu->ut_line); +#endif /* DEBUG */ + memcpy(utmp, pu, sizeof(struct utmp)); + return 0; +} diff --git a/contrib/opie/libopie/hash.c b/contrib/opie/libopie/hash.c new file mode 100644 index 0000000..4029fa9 --- /dev/null +++ b/contrib/opie/libopie/hash.c @@ -0,0 +1,52 @@ +/* hash.c: The opiehash() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3 using the old hash.c as a guide. +*/ + +#include "opie_cfg.h" +#include "opie.h" + +static struct opiemdx_ctx mdx; +static UINT4 mdx_tmp[4]; +#if 0 +static SHA_INFO sha; +#endif /* 0 */ + +VOIDRET opiehash FUNCTION((x, algorithm), VOIDPTR x AND unsigned algorithm) +{ + UINT4 *results = (UINT4 *)x; + + switch(algorithm) { +#if 0 + case 3: + sha_init(&sha); + sha_update(&sha, (BYTE *)x, 8); + sha_final(&sha); + results[0] = sha.digest[0] ^ sha.digest[2] ^ sha.digest[4]; + results[1] = sha.digest[1] ^ sha.digest[3] ^ sha.digest[5]; + break; +#endif /* 0 */ + case 4: + opiemd4init(&mdx); + opiemd4update(&mdx, (unsigned char *)x, 8); + opiemd4final((unsigned char *)mdx_tmp, &mdx); + results[0] = mdx_tmp[0] ^ mdx_tmp[2]; + results[1] = mdx_tmp[1] ^ mdx_tmp[3]; + break; + case 5: + opiemd5init(&mdx); + opiemd5update(&mdx, (unsigned char *)x, 8); + opiemd5final((unsigned char *)mdx_tmp, &mdx); + results[0] = mdx_tmp[0] ^ mdx_tmp[2]; + results[1] = mdx_tmp[1] ^ mdx_tmp[3]; + break; + } +} diff --git a/contrib/opie/libopie/hashlen.c b/contrib/opie/libopie/hashlen.c new file mode 100644 index 0000000..110eef4 --- /dev/null +++ b/contrib/opie/libopie/hashlen.c @@ -0,0 +1,51 @@ +/* hashlen.c: The opiehashlen() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ + +#include "opie_cfg.h" +#include "opie.h" + +VOIDRET opiehashlen FUNCTION((algorithm, in, out, n), int algorithm AND VOIDPTR in AND VOIDPTR out AND int n) +{ + UINT4 *results = (UINT4 *)out; + struct opiemdx_ctx mdx; + UINT4 mdx_tmp[4]; +#if 0 + SHA_INFO sha; +#endif /* 0 */ + + switch(algorithm) { +#if 0 + case 3: + sha_init(&sha); + sha_update(&sha, (BYTE *)in, n); + sha_final(&sha); + results[0] = sha.digest[0] ^ sha.digest[2] ^ sha.digest[4]; + results[1] = sha.digest[1] ^ sha.digest[3] ^ sha.digest[5]; + break; +#endif /* 0 */ + case 4: + opiemd4init(&mdx); + opiemd4update(&mdx, (unsigned char *)in, n); + opiemd4final((unsigned char *)mdx_tmp, &mdx); + results[0] = mdx_tmp[0] ^ mdx_tmp[2]; + results[1] = mdx_tmp[1] ^ mdx_tmp[3]; + break; + case 5: + opiemd5init(&mdx); + opiemd5update(&mdx, (unsigned char *)in, n); + opiemd5final((unsigned char *)mdx_tmp, &mdx); + results[0] = mdx_tmp[0] ^ mdx_tmp[2]; + results[1] = mdx_tmp[1] ^ mdx_tmp[3]; + break; + } +} diff --git a/contrib/opie/libopie/insecure.c b/contrib/opie/libopie/insecure.c new file mode 100644 index 0000000..afab006 --- /dev/null +++ b/contrib/opie/libopie/insecure.c @@ -0,0 +1,146 @@ +/* insecure.c: The opieinsecure() library function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Added result caching. Use + __opiegetutmpentry(). Ifdef around ut_host check. Eliminate + unused variable. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Allow IP loopback. DISPLAY and ut_host must match exactly, + not just the part before the colon. Added work-around for + Sun CDE dtterm bug. Leave the environment as it was + found. Use uname(). + Created at NRL for OPIE 2.2 from opiesubr.c. Fixed pointer + assignment that should have been a comparison. +*/ +#include "opie_cfg.h" + +#include +#include +#include /* ANSI C standard library */ +#include +#include + +#include +#if DOUTMPX +#include +#define utmp utmpx +#endif /* DOUTMPX */ + +#if HAVE_SYS_UTSNAME_H +#include +#endif /* HAVE_SYS_UTSNAME_H */ + +#include "opie.h" + +int opieinsecure FUNCTION_NOARGS +{ +#ifndef NO_INSECURE_CHECK + char *display_name; + char *s; + char *term_name; + int insecure = 0; +#if HAVE_UT_HOST + struct utmp utmp; +#endif /* HAVE_UT_HOST */ + static int result = -1; + + if (result != -1) + return result; + + display_name = (char *) getenv("DISPLAY"); + term_name = (char *) getenv("TERM"); + + if (display_name) { + insecure = 1; + if (s = strchr(display_name, ':')) { + int n = s - display_name; + if (!n) + insecure = 0; + else { + if (!strncmp("unix", display_name, n)) + insecure = 0; + else if (!strncmp("localhost", display_name, n)) + insecure = 0; + else if (!strncmp("loopback", display_name, n)) + insecure = 0; + else if (!strncmp("127.0.0.1", display_name, n)) + insecure = 0; + else { + struct utsname utsname; + + if (!uname(&utsname)) { + if (!strncmp(utsname.nodename, display_name, n)) + insecure = 0; + else { + if (s = strchr(display_name, '.')) { + int n2 = s - display_name; + if (n < n2) + n2 = n; + if (!strncmp(utsname.nodename, display_name, n)) + insecure = 0; + } /* endif display_name is '.' */ + } /* endif hostname != display_name */ + } /* endif was able to get hostname */ + } /* endif display_name == UNIX */ + } + } + } /* endif display_name == ":" */ + if (insecure) + return (result = 1); + + /* If no DISPLAY variable exists and TERM=xterm, + then we probably have an xterm executing on a remote system + with an rlogin or telnet to our system. If it were a local + xterm, then the DISPLAY environment variable would + have to exist. rja */ + if (!display_name && !term_name && !strcmp("xterm", term_name)) + return (result = 1); + +#if HAVE_UT_HOST + memset(&utmp, 0, sizeof(struct utmp)); + if (!__opiegetutmpentry(ttyname(0), &utmp) && utmp.ut_host[0]) { + insecure = 1; + + if (s = strchr(utmp.ut_host, ':')) { + int n = s - utmp.ut_host; + if (!n) + insecure = 0; + else + if (display_name) { + if (!strncmp(utmp.ut_host, display_name, n)) + insecure = 0; +#ifdef SOLARIS + else + if (s = strchr(utmp.ut_host, ' ')) { + *s = ':'; + if (s = strchr(s + 1, ' ')) + *s = '.'; + if (!strncmp(utmp.ut_host, display_name, n)) + insecure = 0; + } +#endif /* SOLARIS */ + } + } + } +#endif /* HAVE_UT_HOST */ + if (insecure) + return (result = 1); + + return (result = 0); +#else /* NO_INSECURE_CHECK */ + return 0; +#endif /* NO_INSECURE_CHECK */ +} diff --git a/contrib/opie/libopie/keycrunch.c b/contrib/opie/libopie/keycrunch.c new file mode 100644 index 0000000..7df86d9 --- /dev/null +++ b/contrib/opie/libopie/keycrunch.c @@ -0,0 +1,64 @@ +/* keycrunch.c: The opiekeycrunch() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3 using the old keycrunch.c as a guide. +*/ + +#include "opie_cfg.h" + +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#if HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ +#include + +#include "opie.h" + +int opiekeycrunch FUNCTION((algorithm, result, seed, secret), int algorithm AND char *result AND char *seed AND char *secret) +{ + int i, rval = -1; + char *c; + + if (!result || !seed || !secret) + return 1; + + i = strlen(seed) + strlen(secret); + if (!(c = malloc(i + 1))) + return -1; + + { + char *c2 = c; + + if (algorithm & 0x10) + while(*c2 = *(secret++)) c2++; + + while(*seed) + if (isspace(*(c2++) = tolower(*(seed++)))) + goto kcret; + + if (!(algorithm & 0x10)) + strcpy(c2, secret); + } + + opiehashlen(algorithm & 0x0f, c, result, i); + rval = 0; + +kcret: + { + char *c2 = c; + while(*c2) + *(c2++) = 0; + } + + free(c); + return rval; +} diff --git a/contrib/opie/libopie/lock.c b/contrib/opie/libopie/lock.c new file mode 100644 index 0000000..d6ea56e --- /dev/null +++ b/contrib/opie/libopie/lock.c @@ -0,0 +1,175 @@ +/* lock.c: The opielock() library function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Do refcounts whether or not we + actually lock. Fixed USER_LOCKING=0 case. + Modified by cmetz for OPIE 2.22. Added reference count for locks. + Changed lock filename/refcount symbol names to better indicate + that they're not user serviceable. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Use "principal" instead of "name" to make it clearer. + Ifdef around some headers, be more careful about allowed + error return values. Check open() return value properly. + Avoid NULL. + Created at NRL for OPIE 2.2 from opiesubr2.c +*/ +#include "opie_cfg.h" +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include +#if HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ +#include "opie.h" + +int __opie_lockrefcount = 0; + +#if USER_LOCKING +char *__opie_lockfilename = (char *)0; + +/* atexit() handler for opielock() */ +static VOIDRET opieunlockaeh FUNCTION_NOARGS +{ + if (__opie_lockfilename) { + __opie_lockrefcount = 0; + opieunlock(); + } +} +#endif /* USER_LOCKING */ + +/* + Serialize (we hope) authentication of user to prevent race conditions. + Creates a lock file with a name of OPIE_LOCK_PREFIX with the user name + appended. This file contains the pid of the lock's owner and a time() + stamp. We use the former to check for dead owners and the latter to + provide an upper bound on the lock duration. If there are any problems, + we assume the lock is bogus. + + The value of this locking and its security implications are still not + completely clear and require further study. + + One could conceivably hack this facility to provide locking of user + accounts after several authentication failures. + + Return -1 on low-level error, 0 if ok, 1 on locking failure. +*/ +int opielock FUNCTION((principal), char *principal) +{ +#if USER_LOCKING + int fh, waits = 0, rval = -1, pid, t, i; + char buffer[128], buffer2[128], *c, *c2; + + if (__opie_lockfilename) { + __opie_lockrefcount++; + return 0; + } + + if (!(__opie_lockfilename = (char *)malloc(sizeof(OPIE_LOCK_PREFIX) + strlen(principal)))) + return -1; + + strcpy(__opie_lockfilename, OPIE_LOCK_PREFIX); + strcat(__opie_lockfilename, principal); + + fh = 0; + while (!fh) + if ((fh = open(__opie_lockfilename, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0) { + if ((fh = open(__opie_lockfilename, O_RDWR, 0600)) < 0) + goto lockret; + if ((i = read(fh, buffer, sizeof(buffer))) <= 0) + goto lockret; + + buffer[sizeof(buffer) - 1] = 0; + buffer[i - 1] = 0; + + if (!(c = strchr(buffer, '\n'))) + break; + + *(c++) = 0; + + if (!(c2 = strchr(c, '\n'))) + break; + + *(c2++) = 0; + + if (!(pid = atoi(buffer))) + break; + + if (!(t = atoi(c))) + break; + + if ((time(0) + OPIE_LOCK_TIMEOUT) < t) + break; + + if (kill(pid, 0)) + break; + + close(fh); + fh = 0; + sleep(1); + if (waits++ > 3) { + rval = 1; + goto lockret; + }; + }; + + sprintf(buffer, "%d\n%d\n", getpid(), time(0)); + i = strlen(buffer) + 1; + if (lseek(fh, 0, SEEK_SET)) { + close(fh); + unlink(__opie_lockfilename); + fh = 0; + goto lockret; + }; + if (write(fh, buffer, i) != i) { + close(fh); + unlink(__opie_lockfilename); + fh = 0; + goto lockret; + }; + close(fh); + if ((fh = open(__opie_lockfilename, O_RDWR, 0600)) < 0) { + unlink(__opie_lockfilename); + goto lockret; + }; + if (read(fh, buffer2, i) != i) { + close(fh); + unlink(__opie_lockfilename); + fh = 0; + goto lockret; + }; + close(fh); + if (memcmp(buffer, buffer2, i)) { + unlink(__opie_lockfilename); + goto lockret; + }; + + __opie_lockrefcount++; + rval = 0; + atexit(opieunlockaeh); + +lockret: + if (fh) + close(fh); + return rval; +#else /* USER_LOCKING */ + __opie_lockrefcount++; + return 0; +#endif /* USER_LOCKING */ +} diff --git a/contrib/opie/libopie/login.c b/contrib/opie/libopie/login.c new file mode 100644 index 0000000..d70280f --- /dev/null +++ b/contrib/opie/libopie/login.c @@ -0,0 +1,130 @@ +/* login.c: The opielogin() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ + +#include "opie_cfg.h" +#include +#include +#include + +#if DOUTMPX +#include +#define pututline(x) pututxline(x) +#define utmp utmpx +#endif /* DOUTMPX */ + +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#include +#if DEBUG +#include +#include +#endif /* DEBUG */ +#include "opie.h" + +int opielogin FUNCTION((line, name, host), char *line AND char *name AND char *host) +{ + struct utmp u; + int rval = 0; + + if (__opiegetutmpentry(line, &u)) { +#if DEBUG + syslog(LOG_DEBUG, "opielogin: __opiegetutmpentry(line=%s, &u) failed", line); +#endif /* DEBUG */ + memset(&u, 0, sizeof(struct utmp)); + if (!strncmp(line, "/dev/", 5)) + strncpy(u.ut_line, line + 5, sizeof(u.ut_line)); + else + strncpy(u.ut_line, line, sizeof(u.ut_line)); +#if DEBUG + syslog(LOG_DEBUG, "opielogin: continuing with ut_line=%s", u.ut_line); +#endif /* DEBUG */ + } + +#if HAVE_UT_TYPE && defined(USER_PROCESS) + u.ut_type = USER_PROCESS; +#endif /* HAVE_UT_TYPE && defined(USER_PROCESS) */ +#if HAVE_UT_PID + u.ut_pid = getpid(); +#endif /* HAVE_UT_PID */ + +#if HAVE_UT_NAME + strncpy(u.ut_name, name, sizeof(u.ut_name)); + u.ut_name[sizeof(u.ut_name)] = 0; +#else /* HAVE_UT_NAME */ +#error No ut_name field in struct utmp? (Please send in a bug report) +#endif /* HAVE_UT_NAME */ + +#if HAVE_UT_HOST + strncpy(u.ut_host, host, sizeof(u.ut_host)); + u.ut_host[sizeof(u.ut_host)] = 0; +#endif /* HAVE_UT_HOST */ + +#if DOUTMPX +#ifdef HAVE_ONE_ARG_GETTIMEOFDAY + gettimeofday(&u->ut_tv); +#else /* HAVE_ONE_ARG_GETTIMEOFDAY */ + gettimeofday(&u->ut_tv, NULL); +#endif /* HAVE_ONE_ARG_GETTIMEOFDAY */ +#else /* DOUTMPX */ + time(&u.ut_time); +#endif /* DOUTMPX */ + + pututline(&u); + endutent(); + +#if DEBUG + syslog(LOG_DEBUG, "opielogin: utmp suceeded"); +#endif /* DEBUG */ + +dowtmp: + { + FILE *f; + +#if DOUTMPX + updutmpx(_PATH_WTMPX, &u); +#else /* DOUTMPX */ + if (!(f = __opieopen(_PATH_WTMP, 2, 0664))) { + rval = -1; +#if DEBUG + syslog(LOG_DEBUG, "opielogin: wtmp open failed: %s (%d)", strerror(errno), errno); +#endif /* DEBUG */ + goto dosetlogin; + } + + if (fwrite(&u, sizeof(struct utmp), 1, f) != sizeof(struct utmp)) { +#if DEBUG + syslog(LOG_DEBUG, "opielogin: wtmp write failed: %s (%d)", strerror(errno), errno); +#endif /* DEBUG */ + rval = -1; + } + + fclose(f); +#endif /* DOUTMPX */ + } + +#if DEBUG + syslog(LOG_DEBUG, "opielogin: wtmp suceeded"); +#endif /* DEBUG */ + +dosetlogin: +#if HAVE_SETLOGIN + setlogin(name); +#endif /* HAVE_SETLOGIN */ + +#if DEBUG + syslog(LOG_DEBUG, "opielogin: rval=%d", rval); +#endif /* DEBUG */ + + return rval; +} diff --git a/contrib/opie/libopie/lookup.c b/contrib/opie/libopie/lookup.c new file mode 100644 index 0000000..e3df681 --- /dev/null +++ b/contrib/opie/libopie/lookup.c @@ -0,0 +1,30 @@ +/* lookup.c: The opielookup() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3 (re-write). +*/ + +#include "opie_cfg.h" +#include +#include "opie.h" + +int opielookup FUNCTION((opie, principal), struct opie *opie AND char *principal) +{ + int i; + + memset(opie, 0, sizeof(struct opie)); + opie->opie_principal = principal; + + if (i = __opiereadrec(opie)) + return i; + + return (opie->opie_flags & __OPIE_FLAGS_RW) ? 0 : 2; +} + diff --git a/contrib/opie/libopie/md4c.c b/contrib/opie/libopie/md4c.c new file mode 100644 index 0000000..fd46857 --- /dev/null +++ b/contrib/opie/libopie/md4c.c @@ -0,0 +1,267 @@ +/* md4c.c: "RSA Data Security, Inc. MD4 Message-Digest Algorithm" + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Use the real memcpy() and memset(). Use unified context + structure. + Modified at NRL for OPIE 2.0. + Originally from RSADSI reference code. +*/ +/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD4 Message-Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD4 Message-Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + */ + +#include "opie_cfg.h" +#include "opie.h" + +/* Constants for MD4Transform routine. + */ +#define S11 3 +#define S12 7 +#define S13 11 +#define S14 19 +#define S21 3 +#define S22 5 +#define S23 9 +#define S24 13 +#define S31 3 +#define S32 9 +#define S33 11 +#define S34 15 + +static VOIDRET MD4Transform __P((UINT4[4], unsigned char[64])); +static VOIDRET Encode __P((unsigned char *, UINT4 *, unsigned int)); +static VOIDRET Decode __P((UINT4 *, unsigned char *, unsigned int)); + +static unsigned char PADDING[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G and H are basic MD4 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ +/* Rotation is separate from addition to prevent recomputation */ + +#define FF(a, b, c, d, x, s) { \ + (a) += F ((b), (c), (d)) + (x); \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define GG(a, b, c, d, x, s) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define HH(a, b, c, d, x, s) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } + +/* MD4 initialization. Begins an MD4 operation, writing a new context. + */ +VOIDRET opiemd4init FUNCTION((context), struct opiemdx_ctx *context) +{ + context->count[0] = context->count[1] = 0; + + /* Load magic initialization constants. */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD4 block update operation. Continues an MD4 message-digest + operation, processing another message block, and updating the + context. + */ +VOIDRET opiemd4update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen) +{ + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int) ((context->count[0] >> 3) & 0x3F); + /* Update number of bits */ + if ((context->count[0] += ((UINT4) inputLen << 3)) + < ((UINT4) inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4) inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. */ + if (inputLen >= partLen) { + memcpy((POINTER) & context->buffer[index], (POINTER) input, partLen); + MD4Transform(context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD4Transform(context->state, &input[i]); + + index = 0; + } else + i = 0; + + /* Buffer remaining input */ + memcpy((POINTER) & context->buffer[index], (POINTER) & input[i], inputLen - i); +} + +/* MD4 finalization. Ends an MD4 message-digest operation, writing the + the message digest and zeroizing the context. + */ +VOIDRET opiemd4final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context) +{ + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + Encode(bits, context->count, 8); + + /* Pad out to 56 mod 64. */ + index = (unsigned int) ((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + opiemd4update(context, PADDING, padLen); + + /* Append length (before padding) */ + opiemd4update(context, bits, 8); + /* Store state in digest */ + Encode(digest, context->state, 16); + + /* Zeroize sensitive information. */ + memset((POINTER) context, 0, sizeof(*context)); +} + +/* MD4 basic transformation. Transforms state based on block. + */ +static VOIDRET MD4Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64]) +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode(x, block, 64); + + /* Round 1 */ + FF(a, b, c, d, x[0], S11); /* 1 */ + FF(d, a, b, c, x[1], S12); /* 2 */ + FF(c, d, a, b, x[2], S13); /* 3 */ + FF(b, c, d, a, x[3], S14); /* 4 */ + FF(a, b, c, d, x[4], S11); /* 5 */ + FF(d, a, b, c, x[5], S12); /* 6 */ + FF(c, d, a, b, x[6], S13); /* 7 */ + FF(b, c, d, a, x[7], S14); /* 8 */ + FF(a, b, c, d, x[8], S11); /* 9 */ + FF(d, a, b, c, x[9], S12); /* 10 */ + FF(c, d, a, b, x[10], S13); /* 11 */ + FF(b, c, d, a, x[11], S14); /* 12 */ + FF(a, b, c, d, x[12], S11); /* 13 */ + FF(d, a, b, c, x[13], S12); /* 14 */ + FF(c, d, a, b, x[14], S13); /* 15 */ + FF(b, c, d, a, x[15], S14); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[0], S21); /* 17 */ + GG(d, a, b, c, x[4], S22); /* 18 */ + GG(c, d, a, b, x[8], S23); /* 19 */ + GG(b, c, d, a, x[12], S24); /* 20 */ + GG(a, b, c, d, x[1], S21); /* 21 */ + GG(d, a, b, c, x[5], S22); /* 22 */ + GG(c, d, a, b, x[9], S23); /* 23 */ + GG(b, c, d, a, x[13], S24); /* 24 */ + GG(a, b, c, d, x[2], S21); /* 25 */ + GG(d, a, b, c, x[6], S22); /* 26 */ + GG(c, d, a, b, x[10], S23); /* 27 */ + GG(b, c, d, a, x[14], S24); /* 28 */ + GG(a, b, c, d, x[3], S21); /* 29 */ + GG(d, a, b, c, x[7], S22); /* 30 */ + GG(c, d, a, b, x[11], S23); /* 31 */ + GG(b, c, d, a, x[15], S24); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[0], S31); /* 33 */ + HH(d, a, b, c, x[8], S32); /* 34 */ + HH(c, d, a, b, x[4], S33); /* 35 */ + HH(b, c, d, a, x[12], S34); /* 36 */ + HH(a, b, c, d, x[2], S31); /* 37 */ + HH(d, a, b, c, x[10], S32); /* 38 */ + HH(c, d, a, b, x[6], S33); /* 39 */ + HH(b, c, d, a, x[14], S34); /* 40 */ + HH(a, b, c, d, x[1], S31); /* 41 */ + HH(d, a, b, c, x[9], S32); /* 42 */ + HH(c, d, a, b, x[5], S33); /* 43 */ + HH(b, c, d, a, x[13], S34); /* 44 */ + HH(a, b, c, d, x[3], S31); /* 45 */ + HH(d, a, b, c, x[11], S32); /* 46 */ + HH(c, d, a, b, x[7], S33); /* 47 */ + HH(b, c, d, a, x[15], S34); /* 48 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + memset((POINTER) x, 0, sizeof(x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static VOIDRET Encode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char) (input[i] & 0xff); + output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff); + output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff); + output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + */ +static VOIDRET Decode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) | + (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24); +} diff --git a/contrib/opie/libopie/md5c.c b/contrib/opie/libopie/md5c.c new file mode 100644 index 0000000..6b20508 --- /dev/null +++ b/contrib/opie/libopie/md5c.c @@ -0,0 +1,304 @@ +/* md5c.c: "RSA Data Security, Inc. MD5 Message-Digest Algorithm" + "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Changed PTR to VOIDPTR. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Don't play macro games with memset/memcpy. Renamed exported + functions to avoid conflicts. Use unified context structure. + Modified at NRL for OPIE 2.1. Minor autoconf mods. + Modified at NRL for OPIE 2.0. + Originally from RSADSI reference code. +*/ +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD5 Message-Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD5 Message-Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + */ + +#include "opie_cfg.h" +#include "opie.h" + +/* Constants for MD5Transform routine. + */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static VOIDRET MD5Transform __P((UINT4[4], unsigned char[64])); + +static unsigned char PADDING[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * Encodes input (UINT4) into output (unsigned char). + * Assumes len is a multiple of 4. + */ +static VOIDRET EEncode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char) (input[i] & 0xff); + output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff); + output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff); + output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff); + } +} + +/* + * Decodes input (unsigned char) into output (UINT4). + * Assumes len is a multiple of 4. + */ +static VOIDRET EDecode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) | + (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24); +} + +/* F, G, H and I are basic MD5 functions. */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + Rotation is separate from addition to prevent recomputation. */ + +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. */ +VOIDRET opiemd5init FUNCTION((context), struct opiemdx_ctx *context) +{ + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* + * MD5 block update operation. Continues an MD5 message-digest + * operation, processing another message block, and updating the + * context. + */ +VOIDRET opiemd5update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen) +{ + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int) ((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((UINT4) inputLen << 3)) < ((UINT4) inputLen << 3)) + context->count[1]++; + + context->count[1] += ((UINT4) inputLen >> 29); + partLen = 64 - index; + + /* Transform as many times as possible. */ + if (inputLen >= partLen) { + memcpy((VOIDPTR)&context->buffer[index], (VOIDPTR)input, partLen); + MD5Transform(context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform(context->state, &input[i]); + + index = 0; + } else + i = 0; + + /* Buffer remaining input */ + memcpy((VOIDPTR) & context->buffer[index], + (VOIDPTR) & input[i], + inputLen - i); +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + */ +VOIDRET opiemd5final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context) +{ + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + EEncode(bits, context->count, 8); + + /* Pad out to 56 mod 64. */ + index = (unsigned int) ((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + opiemd5update(context, PADDING, padLen); + + /* Append length (before padding) */ + opiemd5update(context, bits, 8); + + /* Store state in digest */ + EEncode(digest, context->state, 16); + + /* Zeroize sensitive information. */ + memset((VOIDPTR) context, 0, sizeof(*context)); +} + +/* MD5 basic transformation. Transforms state based on block. */ +static VOIDRET MD5Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64]) +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + EDecode(x, block, 64); + + /* Round 1 */ + FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ + FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ + GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ + II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + memset((VOIDPTR)x, 0, sizeof(x)); +} diff --git a/contrib/opie/libopie/newseed.c b/contrib/opie/libopie/newseed.c new file mode 100644 index 0000000..af4cac7 --- /dev/null +++ b/contrib/opie/libopie/newseed.c @@ -0,0 +1,99 @@ +/* newseed.c: The opienewseed() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.22. +*/ + +#include "opie_cfg.h" +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#include +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#if HAVE_SYS_UTSNAME_H +#include +#endif /* HAVE_SYS_UTSNAME_H */ +#include +#include "opie.h" + +int opienewseed FUNCTION((seed), char *seed) +{ + if (!seed) + return -1; + + if (seed[0]) { + int i; + + if ((i = strlen(seed)) >= OPIE_SEED_MIN) { + long j; + char *c; + + if (i > OPIE_SEED_MAX) + i = OPIE_SEED_MAX; + + c = seed + i - 1; + + while(c != seed) { + if (!isdigit(*c)) + break; + c--; + } + + c++; + + if (j = strtol(c, (char **)0, 10)) { + char buf[OPIE_SEED_MAX]; + + *c = 0; + strcpy(buf, seed); + + if (errno == ERANGE) { + j = 1; + } else { + int k = 1, l = OPIE_SEED_MAX - strlen(buf); + while(l--) k *= 10; + + if (++j >= k) + j = 1; + } + + sprintf(seed, "%s%04d", buf, j); + return 0; + } + } + } + + { + { + time_t now; + time(&now); + srand(now); + } + + { + struct utsname utsname; + + if (uname(&utsname) < 0) { +#if 0 + perror("uname"); +#endif /* 0 */ + utsname.nodename[0] = 'k'; + utsname.nodename[1] = 'e'; + } + utsname.nodename[2] = 0; + + sprintf(seed, "%s%04d", utsname.nodename, (rand() % 9999) + 1); + return 0; + } + } +} + diff --git a/contrib/opie/libopie/open.c b/contrib/opie/libopie/open.c new file mode 100644 index 0000000..0082c34 --- /dev/null +++ b/contrib/opie/libopie/open.c @@ -0,0 +1,61 @@ +/* open.c: The __opieopen() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ +#include "opie_cfg.h" + +#include +#include +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include +#include + +#include "opie.h" + +#if !HAVE_LSTAT +#define lstat(x, y) stat(x, y) +#endif /* !HAVE_LSTAT */ + +FILE *__opieopen FUNCTION((file, rw, mode), char *file AND int rw AND int mode) +{ + FILE *f; + struct stat st; + + if (lstat(file, &st)) { + if (errno != ENOENT) + return NULL; + + if (!(f = fopen(file, "w"))) + return NULL; + + fclose(f); + + if (chmod(file, mode)) + return NULL; + + if (lstat(file, &st)) + return NULL; + } + + if (!S_ISREG(st.st_mode)) + return NULL; + + { + char *fmodes[] = { "r", "r+", "a" }; + + if (!(f = fopen(file, fmodes[rw]))) + return NULL; + } + + return f; +} diff --git a/contrib/opie/libopie/parsechallenge.c b/contrib/opie/libopie/parsechallenge.c new file mode 100644 index 0000000..9dca1e6 --- /dev/null +++ b/contrib/opie/libopie/parsechallenge.c @@ -0,0 +1,70 @@ +/* parsechallenge.c: The _opieparsechallenge() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3 using generator.c as a guide. +*/ + +#include "opie_cfg.h" +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#include "opie.h" + +struct algorithm { + char *name; + int num; +}; + +static struct algorithm algorithms[] = { + { "md5", 5 }, + { "md4", 4 }, + { "sha1", 3 }, + { NULL, 0 }, +}; + +int _opieparsechallenge FUNCTION((buffer, algorithm, sequence, seed), char *buffer AND int *algorithm AND int *sequence AND char **seed) +{ + char *c; + + if (!(c = strchr(buffer, ' '))) + return 1; + + { + struct algorithm *a; + + for (a = algorithms; a->name && strncmp(buffer, a->name, (int)(c - buffer)); a++); + if (!a->name) + return -1; + + *algorithm = a->num; + } + + if ((*sequence = strtoul(++c, &c, 10)) > 9999) + return -1; + + while(*c && isspace(*c)) c++; + if (!*c) + return -1; + + buffer = c; + while(*c && !isspace(*c)) c++; + + { + int i = (int)(c - buffer); + + if ((i > OPIE_SEED_MAX) || (i < OPIE_SEED_MIN)) + return -1; + } + + *seed = buffer; + *c = 0; + + return 0; +} diff --git a/contrib/opie/libopie/passcheck.c b/contrib/opie/libopie/passcheck.c new file mode 100644 index 0000000..3b30d70 --- /dev/null +++ b/contrib/opie/libopie/passcheck.c @@ -0,0 +1,50 @@ +/* passcheck.c: The opiepasscheck() library function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. OPIE_PASS_{MIN,MAX} changed to + OPIE_SECRET_{MIN,MAX}. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Created at NRL for OPIE 2.2 from opiesubr.c. +*/ +#include "opie_cfg.h" + +#include +#include + +#include "opie.h" + +/* + Applies "good password" rules to the secret pass phrase. + + We currently implement the following: + + Passwords must be at least OPIE_SECRET_MIN (10) characters long. + Passwords must be at most OPIE_SECRET_MAX (127) characters long. + + N.B.: Passing NULL pointers to this function is a bad idea. +*/ +int opiepasscheck FUNCTION((secret), char *secret) +{ + int len = strlen(secret); + + if (len < OPIE_SECRET_MIN) + return 1; + + if (len > OPIE_SECRET_MAX) + return 1; + + return 0; +} diff --git a/contrib/opie/libopie/passwd.c b/contrib/opie/libopie/passwd.c new file mode 100644 index 0000000..e50bf17 --- /dev/null +++ b/contrib/opie/libopie/passwd.c @@ -0,0 +1,74 @@ +/* passwd.c: The opiepasswd() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Modified by cmetz for OPIE 2.3. Split most of the function off + and turned this into a front-end for the new __opiewriterec(). + Added code to compute the key from the secret. Use the opie_ + prefix. Use new opieatob8() and opiebtoa8() return values. + Created by cmetz for OPIE 2.22. +*/ + +#include "opie_cfg.h" +#include "opie.h" + +int opiepasswd FUNCTION((old, mode, principal, n, seed, ks), struct opie *old AND int mode AND char *principal AND int n AND char *seed AND char *ks) +{ + int i; + struct opie opie; + + if ((mode & 1) && opieinsecure()) + return -1; + + memset(&opie, 0, sizeof(struct opie)); + + if (old) { + opie.opie_flags = old->opie_flags; + opie.opie_recstart = old->opie_recstart; + opie.opie_extrecstart = old->opie_extrecstart; + } + + opie.opie_principal = principal; + opie.opie_n = n; + opie.opie_seed = seed; + + if (ks) { + char key[8]; + + if (mode & 1) { + if (opiekeycrunch(MDX, key, seed, ks)) + return -1; + for (i = n; i; i--) + opiehash(key, MDX); + if (!(opie.opie_val = opiebtoa8(opie.opie_buf, key))) + return -1; + + if (opiekeycrunch(MDX | 0x10, key, seed, ks)) + return -1; + + if (!(opie.opie_reinitkey = opiebtoa8(opie.opie_extbuf, key))) + return -1; + } else { + if ((opieetob(key, ks) != 1) && !opieatob8(key, ks)) + return 1; + if (!(opie.opie_val = opiebtoa8(opie.opie_buf, key))) + return 1; + } + } + + if (opielock(principal)) + return -1; + + i = __opiewriterec(&opie); + + if (opieunlock()) + return -1; + + return i; +} diff --git a/contrib/opie/libopie/randomchallenge.c b/contrib/opie/libopie/randomchallenge.c new file mode 100644 index 0000000..6e0d5b7 --- /dev/null +++ b/contrib/opie/libopie/randomchallenge.c @@ -0,0 +1,43 @@ +/* randomchallenge.c: The opierandomchallenge() library function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Add sha support. + Modified by cmetz for OPIE 2.22. Don't include stdio.h. + Use opienewseed(). Don't include unneeded headers. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Changed use of gethostname() to uname(). Ifdefed around some + headers. + Created at NRL for OPIE 2.2 from opiesubr2.c +*/ + +#include "opie_cfg.h" +#include "opie.h" + +static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" }; + +/* Generate a random challenge */ +/* This could grow into quite a monster, really. Random is good enough for + most situations; it is certainly better than a fixed string */ +VOIDRET opierandomchallenge FUNCTION((prompt), char *prompt) +{ + char buf[OPIE_SEED_MAX + 1]; + + buf[0] = 0; + if (opienewseed(buf)) + strcpy(buf, "ke4452"); + + sprintf(prompt, "otp-%s %d %s", algids[MDX], (rand() % 499) + 1, buf); +} diff --git a/contrib/opie/libopie/readpass.c b/contrib/opie/libopie/readpass.c new file mode 100644 index 0000000..4dc22e2 --- /dev/null +++ b/contrib/opie/libopie/readpass.c @@ -0,0 +1,304 @@ +/* readpass.c: The opiereadpass() library function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Use TCSAFLUSH always. + Modified by cmetz for OPIE 2.22. Replaced echo w/ flags. + Really use FUNCTION. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Flush extraneous characters up to eol. Handle gobs of possible + erase and kill keys if on a terminal. To do so, use RAW + terminal I/O and handle echo ourselves. (should also help + DOS et al portability). Fixed include order. Re-did MSDOS + and OS/2 includes. Set up VMIN and VTIME. Added some non-UNIX + portability cruft. Limit backspacing and killing. In terminal + mode, eat random other control characters. Added eof handling. + Created at NRL for OPIE 2.2 from opiesubr.c. Change opiestrip_crlf to + opiestripcrlf. Don't strip to seven bits. +*/ +#include "opie_cfg.h" + +#include +#include +#include /* ANSI C standard library */ + +#ifdef unix +#include /* POSIX file control function headers */ +#include /* POSIX Terminal I/O functions */ +#if HAVE_UNISTD_H +#include /* POSIX standard definitions */ +#endif /* HAVE_UNISTD_H */ +#include +#include +#endif /* unix */ + +#ifdef __MSDOS__ +#include +#endif /* __MSDOS__ */ + +#ifdef __OS2__ +#define INCL_KBD +#include +#include +#endif /* __OS2__ */ + +#include "opie.h" + +#define CONTROL(x) (x - 64) + +char *bsseq = "\b \b"; + +#ifdef unix +static jmp_buf jmpbuf; + +static VOIDRET catch FUNCTION((i), int i) +{ + longjmp(jmpbuf, 1); +} +#endif /* unix */ + +char *opiereadpass FUNCTION((buf, len, flags), char *buf AND int len AND int flags) +{ +#ifdef unix + struct termios attr, orig_attr; +#endif /* unix */ + char erase[5]; + char kill[4]; + char eof[4]; + + memset(erase, 0, sizeof(erase)); + memset(kill, 0, sizeof(kill)); + memset(eof, 0, sizeof(eof)); + + /* This section was heavily rewritten by rja following the model of code + samples circa page 151 of the POSIX Programmer's Guide by Donald Lewine, + ISBN 0-937175-73-0. That book is Copyright 1991 by O'Reilly & + Associates, Inc. All Rights Reserved. I recommend the book to anyone + trying to write portable software. rja */ + +#ifdef unix + if (setjmp(jmpbuf)) + goto error; + + signal(SIGINT, catch); +#endif /* unix */ + + /* Flush any pending output */ + fflush(stderr); + fflush(stdout); + +#ifdef unix + /* Get original terminal attributes */ + if (isatty(0)) { + if (tcgetattr(0, &orig_attr)) + return NULL; + + /* copy terminal settings into attr */ + memcpy(&attr, &orig_attr, sizeof(struct termios)); + + attr.c_lflag &= ~(ECHO | ICANON); + attr.c_lflag |= ISIG; + + attr.c_cc[VMIN] = 1; + attr.c_cc[VTIME] = 0; + + erase[0] = CONTROL('H'); + erase[1] = 127; + +#ifdef CERASE + { + char *e = erase; + + while(*e) + if (*(e++) == CERASE) + break; + + if (!*e) + *e = CERASE; + } +#endif /* CERASE */ +#ifdef VERASE + { + char *e = erase; + + while(*e) + if (*(e++) == attr.c_cc[VERASE]) + break; + + if (!*e) + *e = attr.c_cc[VERASE]; + } +#endif /* VERASE */ + + kill[0] = CONTROL('U'); +#ifdef CKILL + { + char *e = kill; + + while(*e) + if (*(e++) == CKILL) + break; + + if (!*e) + *e = CKILL; + } +#endif /* CKILL */ +#ifdef VKILL + { + char *e = kill; + + while(*e) + if (*(e++) == attr.c_cc[VKILL]) + break; + + if (!*e) + *e = attr.c_cc[VKILL]; + } +#endif /* VKILL */ + + eof[0] = CONTROL('D'); +#ifdef CEOF + { + char *e = eof; + + while(*e) + if (*(e++) == CEOF) + break; + + if (!*e) + *e = CEOF; + } +#endif /* CEOF */ +#ifdef VEOF + { + char *e = eof; + + while(*e) + if (*(e++) == attr.c_cc[VEOF]) + break; + + if (!*e) + *e = VEOF; + } +#endif /* VEOF */ + + if (tcsetattr(0, TCSAFLUSH, &attr)) + goto error; + } +#else /* unix */ + erase[0] = CONTROL('H'); + erase[1] = 127; + kill[0] = CONTROL('U'); + eof[0] = CONTROL('D'); + eof[1] = CONTROL('Z'); +#endif /* unix */ + + { + char *c = buf, *end = buf + len, *e; +#ifdef __OS2__ + KBDKEYINFO keyInfo; +#endif /* __OS2__ */ + +loop: +#ifdef unix + if (read(0, c, 1) != 1) + goto error; +#endif /* unix */ +#ifdef MSDOS + *c = bdos(7, 0, 0); +#endif /* MSDOS */ +#ifdef __OS2__ + KbdCharIn(&keyInfo, 0, 0); + *c = keyInfo.chChar; +#endif /* __OS2__ */ + + if ((*c == '\r') || (*c == '\n')) { + *c = 0; + goto restore; + } + + e = eof; + while(*e) + if (*(e++) == *c) + goto error; + + e = erase; + while(*e) + if (*(e++) == *c) { + if (c <= buf) + goto beep; + + if (flags & 1) + write(1, bsseq, sizeof(bsseq) - 1); + c--; + goto loop; + } + + e = kill; + while(*e) + if (*(e++) == *c) { + if (c <= buf) + goto beep; + + if (flags & 1) + while(c-- > buf) + write(1, bsseq, sizeof(bsseq) - 1); + + c = buf; + goto loop; + } + + if (c < end) { + if (*c < 32) + goto beep; + if (flags & 1) + write(1, c, 1); + c++; + } else { + beep: + *c = CONTROL('G'); + write(1, c, 1); + } + + goto loop; + } + +restore: +#ifdef unix + /* Restore previous tty modes */ + if (isatty(0)) + if (tcsetattr(0, TCSAFLUSH, &orig_attr)) + return NULL; + + signal(SIGINT, SIG_DFL); +#endif /* unix */ + + /* After the secret key is taken from the keyboard, the line feed is + written to standard error instead of standard output. That means that + anyone using the program from a terminal won't notice, but capturing + standard output will get the key words without a newline in front of + them. */ + if (!(flags & 4)) { + fprintf(stderr, "\n"); + fflush(stderr); + } + + return buf; + +error: + *buf = 0; + buf = NULL; + goto restore; +} diff --git a/contrib/opie/libopie/readrec.c b/contrib/opie/libopie/readrec.c new file mode 100644 index 0000000..c98daaa --- /dev/null +++ b/contrib/opie/libopie/readrec.c @@ -0,0 +1,218 @@ +/* readrec.c: The __opiereadrec() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3. +*/ +#include "opie_cfg.h" + +#include +#include +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#if HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ +#if HAVE_FCNTL_H +#include +#endif /* HAVE_FCNTL_H */ +#include +#include +#if DEBUG +#include +#endif /* DEBUG */ +#include "opie.h" + +static int parserec FUNCTION((opie), struct opie *opie) +{ + char *c, *c2; + + if (!(c2 = strchr(opie->opie_principal = opie->opie_buf, ' '))) + return -1; + + while(*c2 == ' ') c2++; + *(c2 - 1) = 0; + + if (!(c2 = strchr(c = c2, ' '))) + return -1; + + *(c2++) = 0; + + if (!(opie->opie_n = atoi(c))) + return -1; + + if (!(c2 = strchr(opie->opie_seed = c2, ' '))) + return -1; + + *(c2++) = 0; + + while(*c2 == ' ') c2++; + + if (!(c2 = strchr(opie->opie_val = c2, ' '))) + return -1; + + *(c2++) = 0; + + return 0; +} + +static int parseextrec FUNCTION((opie), struct opie *opie) +{ + char *c; + + if (!(c = strchr(opie->opie_extbuf, ' '))) + return -1; + + *(c++) = 0; + while(*c == ' ') c++; + + if (!(c = strchr(opie->opie_reinitkey = c, ' '))) + return -1; + + *(c++) = 0; + + return 0; +} + +int __opiereadrec FUNCTION((opie), struct opie *opie) +{ + FILE *f = NULL, *f2 = NULL; + int rval = -1; + + if (!(f = __opieopen(STD_KEY_FILE, 0, 0644))) { +#if DEBUG + syslog(LOG_DEBUG, "__opiereadrec: __opieopen(STD_KEY_FILE..) failed!"); +#endif /* DEBUG */ + goto ret; + } + + if (!(f2 = __opieopen(EXT_KEY_FILE, 0, 0600))) { +#if DEBUG + syslog(LOG_DEBUG, "__opiereadrec: __opieopen(EXT_KEY_FILE..) failed!"); +#endif /* DEBUG */ + } + + { + int i; + + if ((i = open(STD_KEY_FILE, O_RDWR)) < 0) { + opie->opie_flags &= ~__OPIE_FLAGS_RW; +#if DEBUG + syslog(LOG_DEBUG, "__opiereadrec: open(STD_KEY_FILE, O_RDWR) failed: %s", strerror(errno)); +#endif /* DEBUG */ + } else { + close(i); + if ((i = open(EXT_KEY_FILE, O_RDWR)) < 0) { + opie->opie_flags &= ~__OPIE_FLAGS_RW; +#if DEBUG + syslog(LOG_DEBUG, "__opiereadrec: open(STD_KEY_FILE, O_RDWR) failed: %s", strerror(errno)); +#endif /* DEBUG */ + } else { + close(i); + opie->opie_flags |= __OPIE_FLAGS_RW; + } + } + } + + if (opie->opie_buf[0]) { + if (fseek(f, opie->opie_recstart, SEEK_SET)) + goto ret; + + if (fgets(opie->opie_buf, sizeof(opie->opie_buf), f)) + goto ret; + + if (parserec(opie)) + goto ret; + + if (opie->opie_extbuf[0]) { + if (!f2) { +#if DEBUG + syslog(LOG_DEBUG, "__opiereadrec: can't read ext file, but could before?"); +#endif /* DEBUG */ + goto ret; + } + + if (fseek(f2, opie->opie_extrecstart, SEEK_SET)) + goto ret; + + if (fgets(opie->opie_extbuf, sizeof(opie->opie_extbuf), f2)) + goto ret; + + if (parseextrec(opie)) + goto ret; + } + + rval = 0; + goto ret; + } + + if (!opie->opie_principal) + return -1; + + { + char *c, principal[OPIE_PRINCIPAL_MAX]; + int i; + + if (c = strchr(opie->opie_principal, ':')) + *c = 0; + if (strlen(opie->opie_principal) > OPIE_PRINCIPAL_MAX) + (opie->opie_principal)[OPIE_PRINCIPAL_MAX] = 0; + + strcpy(principal, opie->opie_principal); + + do { + if ((opie->opie_recstart = ftell(f)) < 0) + goto ret; + + if (!fgets(opie->opie_buf, sizeof(opie->opie_buf), f)) { + rval = 1; + goto ret; + } + + if (parserec(opie)) + goto ret; + } while (strcmp(principal, opie->opie_principal)); + + if (!f2) { + opie->opie_extbuf[0] = rval = 0; + goto ret; + } + + do { + if ((opie->opie_extrecstart = ftell(f2)) < 0) + goto ret; + + if (!fgets(opie->opie_extbuf, sizeof(opie->opie_extbuf), f2)) { + if (feof(f2)) { + opie->opie_reinitkey = NULL; + rval = 0; + } else + rval = 1; + goto ret; + } + + if (parseextrec(opie)) + goto ret; + } while (strcmp(principal, opie->opie_extbuf)); + + rval = 0; + } + +ret: + if (f) + fclose(f); + if (f2) + fclose(f2); + return rval; +} + diff --git a/contrib/opie/libopie/unlock.c b/contrib/opie/libopie/unlock.c new file mode 100644 index 0000000..35c266d --- /dev/null +++ b/contrib/opie/libopie/unlock.c @@ -0,0 +1,103 @@ +/* unlock.c: The opieunlock() library function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Do refcounts whether or not + we actually lock. Fixed USER_LOCKING=0 case. + Modified by cmetz for OPIE 2.22. Added reference count support. + Changed lock filename/refcount symbol names to better indicate + that they're not user serviceable. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration. + Check for read() == -1. ifdef around unistd.h. + Created at NRL for OPIE 2.2 from opiesubr2.c +*/ +#include "opie_cfg.h" +#include +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include +#include "opie.h" + +extern int __opie_lockrefcount; +#if USER_LOCKING +extern char *__opie_lockfilename; +#endif /* USER_LOCKING */ + +/* + Just remove the lock, right? + Well, not exactly -- we need to make sure it's ours. +*/ +int opieunlock FUNCTION_NOARGS +{ +#if USER_LOCKING + int fh, rval = -1, pid, t, i; + char buffer[128], *c, *c2; + + if (--__opie_lockrefcount > 0) + return 0; + + if (!__opie_lockfilename) + return -1; + + if (!(fh = open(__opie_lockfilename, O_RDWR, 0600))) + goto unlockret; + + if ((i = read(fh, buffer, sizeof(buffer))) < 0) + goto unlockret; + + buffer[sizeof(buffer) - 1] = 0; + buffer[i - 1] = 0; + + if (!(c = strchr(buffer, '\n'))) + goto unlockret; + + *(c++) = 0; + + if (!(c2 = strchr(c, '\n'))) + goto unlockret; + + *(c2++) = 0; + + if (!(pid = atoi(buffer))) + goto unlockret; + + if (!(t = atoi(c))) + goto unlockret; + + if ((pid != getpid()) && (time(NULL) + OPIE_LOCK_TIMEOUT <= t) && + (!kill(pid, 0))) { + rval = 1; + goto unlockret1; + } + + rval = 0; + +unlockret: + unlink(__opie_lockfilename); + +unlockret1: + if (fh) + close(fh); + free(__opie_lockfilename); + __opie_lockfilename = NULL; + return rval; +#else /* USER_LOCKING */ + if (__opie_lockrefcount-- > 0) + return 0; + + return -1; +#endif /* USER_LOCKING */ +} diff --git a/contrib/opie/libopie/verify.c b/contrib/opie/libopie/verify.c new file mode 100644 index 0000000..7388a8a --- /dev/null +++ b/contrib/opie/libopie/verify.c @@ -0,0 +1,255 @@ +/* verify.c: The opieverify() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3 using the old verify.c as a guide. +*/ + +#include "opie_cfg.h" +#ifdef HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#include "opie.h" + +#define RESPONSE_STANDARD 0 +#define RESPONSE_WORD 1 +#define RESPONSE_HEX 2 +#define RESPONSE_INIT 3 +#define RESPONSE_INIT_WORD 4 +#define RESPONSE_UNKNOWN 5 + +struct _rtrans { + int type; + char *name; +}; + +static struct _rtrans rtrans[] = { + { RESPONSE_WORD, "word" }, + { RESPONSE_HEX, "hex" }, + { RESPONSE_INIT, "init" }, + { RESPONSE_INIT_WORD, "init-word" }, + { RESPONSE_STANDARD, "" }, + { RESPONSE_UNKNOWN, NULL } +}; + +static char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" }; + +static int changed FUNCTION((opie), struct opie *opie) +{ + struct opie opie2; + + memset(&opie2, 0, sizeof(struct opie)); + opie2.opie_principal = opie->opie_principal; + if (__opiereadrec(&opie2)) + return 1; + + if ((opie2.opie_n != opie->opie_n) || strcmp(opie2.opie_val, opie->opie_val) || strcmp(opie2.opie_seed, opie->opie_seed)) + return 1; + + memset(&opie2, 0, sizeof(struct opie)); + return 0; +} + +int opieverify FUNCTION((opie, response), struct opie *opie AND char *response) +{ + int i, rval = -1; + char *c; + char key[8], fkey[8], lastkey[8]; + struct opie nopie; + + if (!opie || !response) + goto verret; + + if (!opie->opie_principal) +#if DEBUG + abort(); +#else /* DEBUG */ + goto verret; +#endif /* DEBUG */ + + if (!opieatob8(lastkey, opie->opie_val)) + goto verret; + + if (c = strchr(response, ':')) { + *(c++) = 0; + { + struct _rtrans *r; + for (r = rtrans; r->name && strcmp(r->name, response); r++); + i = r->type; + } + } else + i = RESPONSE_STANDARD; + + switch(i) { + case RESPONSE_STANDARD: + i = 1; + + if (opieetob(key, response) == 1) { + memcpy(fkey, key, sizeof(key)); + opiehash(fkey, MDX); + i = memcmp(fkey, lastkey, sizeof(key)); + } + if (i && opieatob8(key, response)) { + memcpy(fkey, key, sizeof(key)); + opiehash(fkey, MDX); + i = memcmp(fkey, lastkey, sizeof(key)); + } + break; + case RESPONSE_WORD: + i = 1; + + if (opieetob(key, c) == 1) { + memcpy(fkey, key, sizeof(key)); + opiehash(fkey, MDX); + i = memcmp(fkey, lastkey, sizeof(key)); + } + break; + case RESPONSE_HEX: + i = 1; + + if (opieatob8(key, c)) { + memcpy(fkey, key, sizeof(key)); + opiehash(fkey, MDX); + i = memcmp(fkey, lastkey, sizeof(key)); + } + break; + case RESPONSE_INIT: + case RESPONSE_INIT_WORD: + { + char *c2; + char newkey[8], ckxor[8], ck[8], cv[8], cvc[8]; + char buf[OPIE_SEED_MAX + 48 + 1]; + + if (!(c2 = strchr(c, ':'))) + goto verret; + + *(c2++) = 0; + + if (i == RESPONSE_INIT) { + if (!opieatob8(key, c)) + goto verret; + } else { + if (opieetob(key, c) != 1) + goto verret; + } + + memcpy(fkey, key, sizeof(key)); + opiehash(fkey, MDX); + + if (memcmp(fkey, lastkey, sizeof(key))) + goto verret; + + if (changed(opie)) + goto verret; + + opie->opie_n--; + + if (!opiebtoa8(opie->opie_val, key)) + goto verret; + + if (__opiewriterec(opie)) + goto verret; + + if (!(c2 = strchr(c = c2, ':'))) + goto verret; + + *(c2++) = 0; + + { + int j; + + if (_opieparsechallenge(c, &j, &(opie->opie_n), &(opie->opie_seed)) || (j != MDX)) + goto verret; + } + + if (!(c2 = strchr(c = c2, ':'))) + goto verret; + + *(c2++) = 0; + + if (i == RESPONSE_INIT) { + if (!opieatob8(newkey, c)) + goto verret; + } else { + if (opieetob(newkey, c) != 1) + goto verret; + } + + if (!opie->opie_reinitkey || (opie->opie_reinitkey[0] == '*')) + goto verwrt; + + if (!(c2 = strchr(c = c2, ':'))) + goto verret; + + *(c2++) = 0; + + if (i == RESPONSE_INIT) { + if (!opieatob8(ckxor, c)) + goto verret; + if (!opieatob8(cv, c2)) + goto verret; + } else { + if (opieetob(ckxor, c) != 1) + goto verret; + if (opieetob(cv, c2) != 1) + goto verret; + } + + if (!opieatob8(ck, opie->opie_reinitkey)) + goto verret; + + c = buf; + memcpy(c, ck, sizeof(ck)); c += sizeof(ck); + memcpy(c, key, sizeof(key)); c += sizeof(key); + c += sprintf(c, "%s 499 %s", algids[MDX], opie->opie_seed); + memcpy(c, newkey, sizeof(newkey)); c += sizeof(newkey); + memcpy(c, ckxor, sizeof(ckxor)); c += sizeof(ckxor); + memcpy(c, ck, sizeof(ck)); c += sizeof(ck); + opiehashlen(MDX, buf, cvc, (unsigned int)c - (unsigned int)buf); + + if (memcmp(cv, cvc, sizeof(cv))) + goto verret; + + for (i = 0; i < 8; i++) + ck[i] ^= ckxor[i]; + + if (!opiebtoa8(opie->opie_reinitkey, ck)) + goto verret; + + memcpy(key, newkey, sizeof(key)); + } + goto verwrt; + case RESPONSE_UNKNOWN: + rval = 1; + goto verret; + default: + rval = -1; + goto verret; + } + + if (i) { + rval = 1; + goto verret; + } + + if (changed(opie)) + goto verret; + + opie->opie_n--; + +verwrt: + if (!opiebtoa8(opie->opie_val, key)) + goto verret; + rval = __opiewriterec(opie); + +verret: + opieunlock(); + memset(opie, 0, sizeof(struct opie)); + return rval; +} diff --git a/contrib/opie/libopie/version.c b/contrib/opie/libopie/version.c new file mode 100644 index 0000000..48b1dc5 --- /dev/null +++ b/contrib/opie/libopie/version.c @@ -0,0 +1,27 @@ +/* version.c: The opieversion() library function. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Created at NRL for OPIE 2.2 from opiesubr.c. +*/ +#include "opie_cfg.h" +#include "opie.h" + +VOIDRET opieversion FUNCTION_NOARGS +{ + printf("\nOPIE %s (%s)\n\n", VERSION, DATE); + exit(0); +} diff --git a/contrib/opie/libopie/writerec.c b/contrib/opie/libopie/writerec.c new file mode 100644 index 0000000..6978669 --- /dev/null +++ b/contrib/opie/libopie/writerec.c @@ -0,0 +1,85 @@ +/* writerec.c: The __opiewriterec() library function. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3 from passwd.c. +*/ +#include "opie_cfg.h" + +#include +#if TM_IN_SYS_TIME +#include +#else /* TM_IN_SYS_TIME */ +#include +#endif /* TM_IN_SYS_TIME */ +#include +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#if HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ +#include "opie.h" + +char *__opienone = "****************"; + +int __opiewriterec FUNCTION((opie), struct opie *opie) +{ + char buf[17], buf2[64]; + time_t now; + FILE *f, *f2 = NULL; + int i = 0; + + time(&now); + if (strftime(buf2, sizeof(buf2), " %b %d,%Y %T", localtime(&now)) < 1) + return -1; + + if (!(opie->opie_flags & __OPIE_FLAGS_READ)) { + struct opie opie2; + i = opielookup(&opie2, opie->opie_principal); + } + + switch(i) { + case 0: + if (!(f = __opieopen(STD_KEY_FILE, 1, 0644))) + return -1; + if (!(f2 = __opieopen(EXT_KEY_FILE, 1, 0600))) + return -1; + if (fseek(f, opie->opie_recstart, SEEK_SET)) + return -1; + if (fseek(f2, opie->opie_extrecstart, SEEK_SET)) + return -1; + break; + case 1: + if (!(f = __opieopen(STD_KEY_FILE, 2, 0644))) + return -1; + if (!(f2 = __opieopen(EXT_KEY_FILE, 2, 0600))) + return -1; + break; + default: + return -1; + } + + if (fprintf(f, "%s %04d %-16s %s %-21s\n", opie->opie_principal, opie->opie_n, opie->opie_seed, opie->opie_val ? opie->opie_val : __opienone, buf2) < 1) + return -1; + + fclose(f); + + if (f2) { + if (fprintf(f2, "%-32s %-16s %-77s\n", opie->opie_principal, opie->opie_reinitkey ? opie->opie_reinitkey : __opienone, "") < 1) + return -1; + + fclose(f2); + } + + return 0; +} diff --git a/contrib/opie/logwtmp.c b/contrib/opie/logwtmp.c new file mode 100644 index 0000000..4d9dcbf --- /dev/null +++ b/contrib/opie/logwtmp.c @@ -0,0 +1,154 @@ +/* logwtmp.c: Put an entry in the wtmp file. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.22. Call gettimeofday() properly. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Ifdef around some headers. Added file close hook. + Modified at NRL for OPIE 2.1. Set process type for HPUX. + Modified at NRL for OPIE 2.0. + Originally from BSD. +*/ +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "opie_cfg.h" + +#include +#if HAVE_SYS_TIME_H +#include +#endif /* HAVE_SYS_TIME_H */ +#include +#include +#include +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ + +#include "opie.h" + +static int fd = -1; + +#if DOUTMPX +static int fdx = -1; +#include +#endif /* DOUTMPX */ + +#ifndef _PATH_WTMP +#define _PATH_WTMP "/usr/adm/wtmp" +#endif + +#ifndef _PATH_WTMPX +#define _PATH_WTMPX "/usr/adm/wtmpx" +#endif /* _PATH_UTMPX */ + +/* + * Modified version of logwtmp that holds wtmp file open + * after first call, for use with ftp (which may chroot + * after login, but before logout). + */ +VOIDRET logwtmp FUNCTION((line, name, host), char *line AND char *name AND char *host) +{ + struct utmp ut; + +#if DOUTMPX + struct utmpx utx; +#endif /* DOUTMPX */ + struct stat buf; + + memset(&ut, 0, sizeof(struct utmp)); + + if (!line) { + close(fd); +#if DOUTMPX + close(fdx); +#endif /* DOUTMPX */ + } + + if (fd < 0 && (fd = open(_PATH_WTMP, O_WRONLY | O_APPEND, 0)) < 0) + return; + if (fstat(fd, &buf) == 0) { +#if HAVE_UT_TYPE && defined(USER_PROCESS) + ut.ut_type = USER_PROCESS; +#endif /* HAVE_UT_TYPE && defined(USER_PROCESS) */ +#if HAVE_UT_PID + ut.ut_pid = getpid(); +#endif /* HAVE_UT_PID */ + strncpy(ut.ut_line, line, sizeof(ut.ut_line)); + strncpy(ut.ut_name, name, sizeof(ut.ut_name)); +#if !DOUTMPX + strncpy(ut.ut_host, host, sizeof(ut.ut_host)); +#endif /* !DOUTMPX */ + time(&ut.ut_time); + if (write(fd, (char *) &ut, sizeof(struct utmp)) != + sizeof(struct utmp)) + ftruncate(fd, buf.st_size); + } +#if DOUTMPX + memset(&utx, 0, sizeof(struct utmpx)); + + if (fdx < 0 && (fdx = open(WTMPX_FILE, O_WRONLY | O_APPEND, 0)) < 0) + return; + if (fstat(fdx, &buf) == 0) { + strncpy(utx.ut_line, line, sizeof(utx.ut_line)); + strncpy(utx.ut_name, name, sizeof(utx.ut_name)); + strncpy(utx.ut_host, host, sizeof(utx.ut_host)); +#if HAVE_GETTIMEOFDAY +#if HAVE_ONE_ARG_GETTIMEOFDAY + gettimeofday(&utx.ut_tv); +#else /* HAVE_ONE_ARG_GETTIMEOFDAY */ + gettimeofday(&utx.ut_tv, NULL); +#endif /* HAVE_ONE_ARG_GETTIMEOFDAY */ +#endif /* HAVE_GETTIMEOFDAY */ + if (write(fdx, (char *) &utx, sizeof(struct utmpx)) != + sizeof(struct utmpx)) + ftruncate(fdx, buf.st_size); + } +#endif /* DOUTMPX */ +} diff --git a/contrib/opie/opie.4 b/contrib/opie/opie.4 new file mode 100644 index 0000000..97eb73d --- /dev/null +++ b/contrib/opie/opie.4 @@ -0,0 +1,346 @@ +.\" opie.4: Overview of the OPIE software. +.\" +.\" %%% portions-copyright-cmetz +.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights +.\" Reserved. The Inner Net License Version 2 applies to these portions of +.\" the software. +.\" You should have received a copy of the license with this software. If +.\" you didn't get a copy, you may request one from . +.\" +.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan +.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned +.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +.\" License Agreement applies to this software. +.\" +.\" History: +.\" +.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation. Removed +.\" references to the old square brackets challenge delimiters. +.\" Modified at NRL for OPIE 2.01. Updated UNIX trademark credit. +.\" Definition of "seed" written by Neil Haller of Bellcore +.\" Written at NRL for OPIE 2.0. +.\" +.TH OPIE 4 "January 10, 1995" +.SH NAME +.B OPIE \- One-time Passwords In Everything +.SH DESCRIPTION +.LP +OPIE is a package derived from the Bellcore S/Key Version 1 distribution +that helps to secure a system against replay attacks (see below). It does so +using a secure hash function and a challenge/response system. It provides +replacements for the +.IR login (1), +.IR su (1), +and +.IR ftpd (8) +programs that use OPIE +authentication as well as demonstrate how a program might be adapted to use +OPIE authentication. OPIE was developed at and for the United States Naval +Research Laboratory (NRL). OPIE is derived in part from Berkeley Standard +Distribution UNIX and the Bellcore S/Key Version 1 distribution. +.LP +From the average user's perspective, OPIE is a nuisance that prevents their +account from being broken into. The first time a user wishes to use OPIE, +(s)he needs to use the +.IR opiepasswd (1) +command to put an entry for them into +the OPIE database. The user can then use OPIE to authenticate themselves +with any program that supports it. If no other clients are being used, +this means they can use OPIE to +.I telnet, +.I rlogin, +or +.I ftp +into the system, +log in on a terminal port (like a modem), or switch to another user's +account. When they would normally be asked for a password, they will get +a challenge from the server. They then need to copy that challenge (or +re-type, if they don't have the ability to copy and paste through something +like a window system) to their calculator program, enter their password, +then copy (or re-type) the response from the calculator as their password. +While this will seem cumbersome at first, with some practice, it becomes +easy. + +.SH TERMS +.TP +.I user name +The name that the system knows you as. For example, "jdoe". +.TP +.I secret password +A password, usually selected by the user, that is needed to gain access to the +system. For example, "SEc1_rt". +.TP +.I challenge +A packet of information output by a system when it wishes to authenticate a +user. In OPIE, this is a three-item group consisting of a hash identifier, +a sequence number, and a seed. This +information is needed by the OPIE calculator to generate a proper response. +For example, "otp-md5 95 wi14321". +.TP +.I response +A packet of information generated from a challenge that is used by a system to +authenticate a user. In OPIE, this is a group of six words that is generated by +the calculator given the challenge and the secret password. For example, +"PUP SOFT ROSE BIAS FLAG END". +.TP +.I seed +A piece of information that is used in conjunction with the secret password +and sequence numer to compute the response. Its purpose is to allow the same +secret password to be used for multiple sequences, by changing the seed, or +for authentication to multiple machines by using different seeds. +.TP +.I sequence number +A counter used to keep track of key iterations. In OPIE, each time a successful +response is received by the system, the sequence number is decremented. For +example, "95". +.TP +.I hash identifier +A piece of text that identifies the actual algorithm that needs to be used to +generate a proper response. In OPIE, the only two valid hash identifiers are +"otp-md4", which selects MD4 hashing, and "otp-md5", which selects MD5. + +.SH REPLAY ATTACKS +When you use a network terminal program like +.IR telnet (1) +or even use a modem to log into a +computer system, you need a user name and a secret password. Anyone who can +provide those to the system is recognized as you because, in theory, only you +would have your secret password. Unfortunately, it is now easy to listen in +on many computer communications media. From modem communication to many +networks, your password is not usually safe over remote links. If a +cracker can listen in when you send your password, (s)he then has a copy +of your password that can be used at any time in the future to access your +account. On more than one occasion, major sites on the Internet have been +broken into exactly this way. +.LP +All an attacker has to +do is capture your password once and then replay it to the server when it's +asked for. Even if the password is communicated between machines in encoded +or encrypted form, as long as a cracker can get in by simply replaying +a previously captured communication, you are at risk. Up until very recently, +Novell NetWare was vulnerable this way. A cracker couldn't find out what your +password actually is, but (s)he didn't need to -- all that was necessary to +get into your account was to capture the encrypted password and send that +back to the server when asked for it. + +.SH ONE-TIME PASSWORDS +One solution to the problem of replay attacks +is to keep changing the way that a password is being encoded so that what is +sent over the link to another system can only be used once. If you can do that, +then a cracker can replay it as many times as (s)he wants -- it's just not +going to get them anywhere. It's important, however, to make sure you encode +the password in such a way that the cracker can't use the encoded version to +figure out what the password is or what a future encoded password will be. +Otherwise, while still an improvement over no encoding or a fixed encoding, +you can still be broken into. + +.SH THE S/KEY ALGORITHM + +A solution to this whole problem was invented by Lamport in 1981. This +technique was implemented by Haller, Karn, and Walden at Bellcore. They +They created a free software package called "S/Key" that used an algorithm +called a cryptographic checksum. A cryptographic checksum is a strong one-way +function such that, knowing the result of such a function, an attacker still +cannot feasably determine the input. Further, unlike cyclic redundancy +checksums (CRCs), cryptographic checksums have few inputs that result in the +same output. +.LP +In S/Key, what changes is the number of +times the password is run through the secure hash. The password is run through +the secure hash once, then the output of the hash is run through the secure +hash again, that output is run through the secure hash again, and so on until +the number of times the password has been run through the secure hash is equal +to the desired sequence number. This is much slower than just, say, putting +the sequence number in before the password and running that through the secure +hash once, but it gains you one significant benefit. The server machine you +are trying to connect to has to have some way to determine whether the output +of that whole mess is right. If it stores it either without any encoding or +with a normal encoding, a cracker could still get at your password. But if it +stores it with a secure hash, then how does it account for the response +changing every time because the sequence number is changing? Also what if you +can never get to the machine any way that can't be listened in on? How do you +change your password without sending it over the link? +.LP +The clever solution +devised by Lamport is to keep in mind that the sequence number is +always decrementing by one and that, in the S/Key system, simply by running any +response with a sequence number N through the secure hash, you can get the +response with a sequence number N+1, but you can't go the other way. At any +given time, call the sequence number of the last valid response that the +system got N+1 and the sequence number of the response you are giving it N. +If the password that generated the response for N is the same as the one for +N+1, then you should be able to run the response for N through the secure hash +one more time, for a total of N+1 times, and get the same response as you got +back for N+1. Once you compare the two and find that they are the same, you +subtract one from N so that, now, the key for N that you just verified becomes +the new key for N+1 that you can store away to use the next time you need to +verify a key. This also means that if you need to change your password but +don't have a secure way to access your machine, all the system really needs to +have to verify your password is a valid response for one more than the sequence +number you want to start with. +.LP +Just for good measure, each side of +all of this uses a seed in conjunction with your password when it actually +generates and verifies the responses. This helps to jumble things up a little +bit more, just in case. Otherwise, someone with a lot of time and disk space +on their hands could generate all the responses for a lot of frequent passwords +and defeat the system. +.LP +This is not, by any means, the best explanation of how the S/Key algorithm +works or some of the more minor details. For that, you should go to some of +the papers now published on the topic. It is simply a quick-and-dirty +introduction to what's going on under the hood. + +.SH OPIE COMPONENTS + +Included in the OPIE distribution are three OPIE client programs: +.IR opielogin (1), +.IR opiesu (1), +and +.IR opieftpd (8). +These three programs are modified versions of the +freely available 4.3BSD Net/2 versions of +.IR login (1), +.IR su (1), +and +.IR ftpd (8), +respectively. Although most of the modifications actually done to them are so +that they will work on as many machines as possible, they also have been +modified to support OPIE for authentication. As you will see from the source, +it is not very difficult to add support for OPIE to other programs. +.LP +There are also three programs in the OPIE distribution that are specific to +the OPIE system: +.IR opiepasswd (1), +which allows a user to set and change their +OPIE password, +.IR opieinfo (1), +which allows a user to find out what their current +sequence number and seed are, and +.IR opiekey(1), +which is an OPIE key calculator. + +.LP ADDING OPIE TO OTHER PROGRAMS + +Adding OPIE authentication to programs other than the ones included as clients +in the OPIE distribution isn't very difficult. First, you will need to make +sure that the program includes somewhere. Then, below the other +includes such as , but before variable declarations, you need to +include "opie.h". You need to add a variable of type "struct opie" to your +program, you need to make sure that the buffer that you use to get a password +from the user is big enough to hold OPIE_RESPONSE_MAX+1 characters, and you +need to have a buffer in which to store the challenge string that is big enough +to hold OPIE_PROMPT_MAX+1 characters. +.LP +When you are ready to output the challenge string and know the user's name, +you would use a call to opiechallenge. Later, to verify the response received, +you would use a call to opieverify. For example: +.sp 0 + +.sp 0 + #include +.sp 0 + . +.sp 0 + . +.sp 0 + #include "opie.h" +.sp 0 + . +.sp 0 + . +.sp 0 + char *user_name; +.sp 0 + /* Always remember the trailing null! */ +.sp 0 + char password[OPIE_RESPONSE_MAX+1]; +.sp 0 + . +.sp 0 + . +.sp 0 + struct opie opiedata; +.sp 0 + char opieprompt[OPIE_PROMPT_MAX+1]; +.sp 0 + . +.sp 0 + . +.sp 0 + opiechallenge(&opiedata, user_name, &opieprompt); +.sp 0 + . +.sp 0 + . +.sp 0 + if (opieverify(&opiedata, password)) { +.sp 0 + printf("Login incorrect"); +.sp 0 +.SH TERMINAL SECURITY AND OPIE + +When using OPIE, you need to be careful not to allow your password to be +communicated over an insecure channel where someone might be able to listen +in and capture it. OPIE can protect you against people who might get your +password from snooping on the line, but only if you make sure that the password +itself never gets sent over the line. The important thing is to always run the +OPIE calculator on whichever machine you are actually using - never on a machine +you are connected to by network or by dialup. +.LP +You need to be careful about the +X Window System, because it changes things quite a bit. For instance, if you +run an xterm (or your favorite equivalent) on another machine and display it +on your machine, you should not run an OPIE calculator in that window. When you +type in your secret password, it still gets transmitted over the network to go +to the machine the xterm is running on. People with machines such as +X terminals that can only run the calculator over the network are in an +especially precarious position because they really have no choice. Also, with +the X Window System, as with some other window system (NeWS as an example), +it is sometimes possible for people to read your keystrokes and capture your +password even if you are running the OPIE calculator on your local machine. +You should always use the best security mechanism available on your system to +protect your X server, be it XDM-AUTHORIZATION-1, XDM-MAGIC-COOKIE-1, or host +access control. *Never* just allow any machine to connect to your server +because, by doing so, you are allowing any machine to read any of your windows +or your keystrokes without you knowing it. + +.SH SEE ALSO +.BR opie (4), +.BR opiekeys (5), +.BR opieaccess (5), +.BR opiekey (1), +.BR opieinfo (1), +.BR opiepasswd (1), +.BR opielogin (1), +.BR opieftpd (8) +.sp +Lamport, L. "Password Authentication with Insecure Communication", +Communications of the ACM 24.11 (November 1981), pp. 770-772. +.sp +Haller, N. "The S/KEY One-Time Password System", Proceedings of the ISOC +Symposium on Network and Distributed System Security, February 1994, +San Diego, CA. +.sp +Haller, N. and Atkinson, R, "On Internet Authentication", RFC-1704, +DDN Network Information Center, October 1994. +.sp +Rivest, R. "The MD5 Message Digest Algorithm", RFC-1321, +DDN Network Information Center, April 1992. +.sp +Rivest, R. "The MD4 Message Digest Algorithm", RFC-1320, +DDN Network Information Center, April 1992. + +.SH AUTHOR +Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden +of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and +Craig Metz. + +S/Key is a trademark of Bell Communications Research (Bellcore). +UNIX is a trademark of X/Open. + +.SH CONTACT +OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join, +send an email request to: +.sp +skey-users-request@thumper.bellcore.com diff --git a/contrib/opie/opie.h b/contrib/opie/opie.h new file mode 100644 index 0000000..99f0e09 --- /dev/null +++ b/contrib/opie/opie.h @@ -0,0 +1,224 @@ +/* opie.h: Data structures and values for the OPIE authentication + system that a program might need. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Renamed PTR to VOIDPTR. Added + re-init key and extension file fields to struct opie. Added + opie_ prefix on struct opie members. Added opie_flags field + and definitions. Added more prototypes. Changed opiehash() + prototype. + Modified by cmetz for OPIE 2.22. Define __P correctly if this file + is included in a third-party program. + Modified by cmetz for OPIE 2.2. Re-did prototypes. Added FUNCTION + definition et al. Multiple-include protection. Added struct + utsname fake. Got rid of gethostname() cruft. Moved UINT4 + here. Provide for *seek whence values. Move MDx context here + and unify. Re-did prototypes. + Modified at NRL for OPIE 2.0. + Written at Bellcore for the S/Key Version 1 software distribution + (skey.h). +*/ +#ifndef _OPIE_H +#define _OPIE_H + +#if _OPIE + +#if HAVE_VOIDPTR +#define VOIDPTR void * +#else /* HAVE_VOIDPTR */ +#define VOIDPTR char * +#endif /* HAVE_VOIDPTR */ + +#if HAVE_VOIDRET +#define VOIDRET void +#else /* HAVE_VOIDRET */ +#define VOIDRET +#endif /* HAVE_VOIDRET */ + +#if HAVE_VOIDARG +#define NOARGS void +#else /* HAVE_VOIDARG */ +#define NOARGS +#endif /* HAVE_VOIDARG */ + +#if HAVE_ANSIDECL +#define FUNCTION(arglist, args) (args) +#define AND , +#else /* HAVE_ANSIDECL */ +#define FUNCTION(arglist, args) arglist args; +#define AND ; +#endif /* HAVE_ANSIDECL */ + +#define FUNCTION_NOARGS () + +#ifndef __P +#if HAVE_ANSIPROTO +#define __P(x) x +#else /* HAVE_ANSIPROTO */ +#define __P(x) () +#endif /* HAVE_ANSIPROTO */ +#endif /* __P */ + +#ifndef HAVE_SYS_UTSNAME_H +struct utsname { + char nodename[65]; + }; +#endif /* HAVE_SYS_UTSNAME_H */ + +#ifndef _SC_OPEN_MAX +#define _SC_OPEN_MAX 1 +#endif /* _SC_OPEN_MAX */ + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 1024 +#endif /* MAXHOSTNAMELEN */ + +#else /* _OPIE */ +#ifdef __STDC__ +#define VOIDRET void +#define VOIDPTR void * +#else /* __STDC__ */ +#define VOIDRET +#define VOIDPTR char * +#endif /* __STDC__ */ +#endif /* _OPIE */ + +#ifndef __P +#ifdef __ARGS +#define __P __ARGS +#else /* __ARGS */ +#ifdef __STDC__ +#define __P(x) x +#else /* __STDC__ */ +#define __P(x) () +#endif /* __STDC__ */ +#endif /* __ARGS */ +#endif /* __P */ + +struct opie { + int opie_flags; + char opie_buf[256]; + char *opie_principal; + int opie_n; + char *opie_seed; + char *opie_val; + long opie_recstart; + char opie_extbuf[129]; /* > OPIE_PRINCIPAL_MAX + 1 + 16 + 2 + 1 */ + long opie_extrecstart; + char *opie_reinitkey; +}; + +#define __OPIE_FLAGS_RW 1 +#define __OPIE_FLAGS_READ 2 + +/* Minimum length of a secret password */ +#ifndef OPIE_SECRET_MIN +#define OPIE_SECRET_MIN 10 +#endif /* OPIE_SECRET_MIN */ + +/* Maximum length of a secret password */ +#ifndef OPIE_SECRET_MAX +#define OPIE_SECRET_MAX 127 +#endif /* OPIE_SECRET_MAX */ + +/* Minimum length of a seed */ +#ifndef OPIE_SEED_MIN +#define OPIE_SEED_MIN 5 +#endif /* OPIE_SEED_MIN */ + +/* Maximum length of a seed */ +#ifndef OPIE_SEED_MAX +#define OPIE_SEED_MAX 16 +#endif /* OPIE_SEED_MAX */ + +/* Maximum length of a challenge (otp-md? 9999 seed) */ +#ifndef OPIE_CHALLENGE_MAX +#define OPIE_CHALLENGE_MAX (7+1+4+1+OPIE_SEED_MAX) +#endif /* OPIE_CHALLENGE_MAX */ + +/* Maximum length of a response that we allow */ +#ifndef OPIE_RESPONSE_MAX +#define OPIE_RESPONSE_MAX (9+1+19+1+9+OPIE_SEED_MAX+1+19+1+19+1+19) +#endif /* OPIE_RESPONSE_MAX */ + +/* Maximum length of a principal (read: user name) */ +#ifndef OPIE_PRINCIPAL_MAX +#define OPIE_PRINCIPAL_MAX 32 +#endif /* OPIE_PRINCIPAL_MAX */ + +#ifndef __alpha +#define UINT4 unsigned long +#else /* __alpha */ +#define UINT4 unsigned int +#endif /* __alpha */ + +struct opiemdx_ctx { + UINT4 state[4]; + UINT4 count[2]; + unsigned char buffer[64]; +}; + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif /* SEEK_SET */ + +#ifndef SEEK_END +#define SEEK_END 2 +#endif /* SEEK_END */ + +int opieaccessfile __P((char *)); +int rdnets __P((long)); +int isaddr __P((register char *)); +int opiealways __P((char *)); +char *opieatob8 __P((char *,char *)); +VOIDRET opiebackspace __P((char *)); +char *opiebtoa8 __P((char *,char *)); +char *opiebtoe __P((char *,char *)); +char *opiebtoh __P((char *,char *)); +int opieetob __P((char *,char *)); +int opiechallenge __P((struct opie *,char *,char *)); +int opiegenerator __P((char *,char *,char *)); +int opiegetsequence __P((struct opie *)); +VOIDRET opiehash __P((VOIDPTR, unsigned)); +int opiehtoi __P((register char)); +int opiekeycrunch __P((int, char *, char *, char *)); +int opielock __P((char *)); +int opielookup __P((struct opie *,char *)); +VOIDRET opiemd4init __P((struct opiemdx_ctx *)); +VOIDRET opiemd4update __P((struct opiemdx_ctx *,unsigned char *,unsigned int)); +VOIDRET opiemd4final __P((unsigned char *,struct opiemdx_ctx *)); +VOIDRET opiemd5init __P((struct opiemdx_ctx *)); +VOIDRET opiemd5update __P((struct opiemdx_ctx *,unsigned char *,unsigned int)); +VOIDRET opiemd5final __P((unsigned char *,struct opiemdx_ctx *)); +int opiepasscheck __P((char *)); +VOIDRET opierandomchallenge __P((char *)); +char * opieskipspace __P((register char *)); +VOIDRET opiestripcrlf __P((char *)); +int opieverify __P((struct opie *,char *)); +int opiepasswd __P((struct opie *, int, char *, int, char *, char *)); +char *opiereadpass __P((char *, int, int)); +int opielogin __P((char *line, char *name, char *host)); + +#if _OPIE +struct utmp; +int __opiegetutmpentry __P((char *, struct utmp *)); +#ifdef EOF +FILE *__opieopen __P((char *, int, int)); +#endif /* EOF */ +int __opiereadrec __P((struct opie *)); +int __opiewriterec __P((struct opie *)); +#endif /* _OPIE */ +#endif /* _OPIE_H */ diff --git a/contrib/opie/opie_cfg.h b/contrib/opie/opie_cfg.h new file mode 100644 index 0000000..57490de --- /dev/null +++ b/contrib/opie/opie_cfg.h @@ -0,0 +1,167 @@ +/* opie_cfg.h: Various configuration-type pieces of information for OPIE. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Splatted with opie_auto.h. + Obseleted many symbols. Changed OPIE_PASS_{MIN,MAX} to + OPIE_SECRET_{MIN,MAX}. Fixed SHADOW+UTMP definitions. + Removed a lot of symbols. + Modified by cmetz for OPIE 2.2. Got rid of ANSIPROTO and ARGS. + Got rid of TRUE and FALSE definitions. Moved UINT4 to + opie.h and removed UINT2. + Modified at NRL for OPIE 2.1. Fixed sigprocmask declaration. + Gutted for autoconf. Split up for autoconf. + Written at NRL for OPIE 2.0. + + History of opie_auto.h: + + Modified by cmetz for OPIE 2.22. Support the Solaris TTYPROMPT drain + bamage on all systems -- it doesn't hurt others, and it's + not something Autoconf can check for yet. + Modified by cmetz for OPIE 2.2. Don't replace sigprocmask by ifdef. + Added configure check for LS_COMMAND. Added setreuid/setgid + band-aids. + Modified at NRL for OPIE 2.2. Require /etc/shadow for Linux to use + shadow passwords. + Modified at NRL for OPIE 2.11. Removed version defines. + Modified at NRL for OPIE 2.1. Fixed sigprocmask declaration. + Gutted for autoconf. Split up for autoconf. + Written at NRL for OPIE 2.0. +*/ + +#define VERSION "2.3" +#define DATE "Sunday, September 22, 1996" + +#ifndef unix +#define unix 1 +#endif /* unix */ + +#include "config.h" +#include "options.h" + +/* System characteristics */ + +#if HAVE_GETUTXLINE && HAVE_UTMPX_H +#define DOUTMPX 1 +#else /* HAVE_GETUTXLINE && HAVE_UTMPX_H */ +#define DOUTMPX 0 +#endif /* HAVE_GETUTXLINE && HAVE_UTMPX_H */ + +/* Adapted from the Autoconf hypertext info pages */ +#if HAVE_DIRENT_H +#include +#else /* HAVE_DIRENT_H */ +#define dirent direct +#if HAVE_SYS_NDIR_H +#include +#endif /* HAVE_SYS_NDIR_H */ +#if HAVE_SYS_DIR_H +#include +#endif /* HAVE_SYS_DIR_H */ +#if HAVE_NDIR_H +#include +#endif /* HAVE_NDIR_H */ +#endif /* HAVE_DIRENT_H */ + +#ifndef MAIL_DIR +#ifdef PATH_MAIL +#define MAIL_DIR PATH_MAIL +#else /* PATH_MAIL */ +#ifdef _PATH_MAIL +#define MAIL_DIR _PATH_MAIL +#else /* _PATH_MAIL */ +#ifdef _PATH_MAILDIR +#define MAIL_DIR _PATH_MAILDIR +#else /* _PATH_MAILDIR */ +#define MAIL_DIR "/usr/spool/mail" +#endif /* _PATH_MAILDIR */ +#endif /* _PATH_MAIL */ +#endif /* PATH_MAIL */ +#endif /* MAIL_DIR */ + +#if HAVE_SHADOW_H && HAVE_GETSPENT && HAVE_ENDSPENT +#if defined(linux) && !HAVE_ETC_SHADOW +#define HAVE_SHADOW 0 +#else /* defined(linux) && !HAVE_ETC_SHADOW */ +#define HAVE_SHADOW 1 +#endif /* defined(linux) && !HAVE_ETC_SHADOW */ +#endif /* HAVE_SHADOW_H && HAVE_GETSPENT && HAVE_ENDSPENT */ + +#if !HAVE_SETEUID && HAVE_SETREUID +#define seteuid(x) setreuid(-1, x) +#endif /* !HAVE_SETEUID && HAVE_SETREUID */ + +#if !HAVE_SETEGID && HAVE_SETREGID +#define setegid(x) setregid(-1, x) +#endif /* !HAVE_SETEGID && HAVE_SETREGID */ + +/* If the user didn't specify, default to MD5 */ +#ifndef MDX +#define MDX 5 +#endif /* MDX */ + +#ifndef _PATH_BSHELL +#define _PATH_BSHELL "/bin/sh" +#endif + +#ifndef _PATH_DEVNULL +#define _PATH_DEVNULL "/dev/null" +#endif + +#ifndef _PATH_FTPUSERS +#define _PATH_FTPUSERS "/etc/ftpusers" +#endif + +#ifndef TTYGRPNAME +#define TTYGRPNAME "tty" /* name of group to own ttys */ +#endif + +#ifndef NO_LOGINS_FILE +#define NO_LOGINS_FILE "/etc/nologin" +#endif + +#ifndef QUIET_LOGIN_FILE +#define QUIET_LOGIN_FILE ".hushlogin" +#endif + +#ifndef OPIE_ALWAYS_FILE +#define OPIE_ALWAYS_FILE ".opiealways" +#endif + +#ifndef OPIE_LOCK_PREFIX +#define OPIE_LOCK_PREFIX "/tmp/opie-lock." +#endif + +#ifndef OPIE_LOCK_TIMEOUT +#define OPIE_LOCK_TIMEOUT (30*60) +#endif + +#ifndef MOTD_FILE +#define MOTD_FILE "/etc/motd" +#endif + +#ifndef NBBY +#define NBBY 8 /* Reasonable for modern systems */ +#endif /* NBBY */ + +#ifndef LOGIN_PATH +#define LOGIN_PATH "/usr/ucb:/bin:/usr/bin" +#endif /* LOGIN_PATH */ + +#ifndef POINTER +#define POINTER unsigned char * +#endif /* POINTER */ + +#define _OPIE 1 diff --git a/contrib/opie/opieaccess.5 b/contrib/opie/opieaccess.5 new file mode 100644 index 0000000..33ab6dd --- /dev/null +++ b/contrib/opie/opieaccess.5 @@ -0,0 +1,87 @@ +.\" opieaccess.5: Manual page describing the /etc/opieaccess file. +.\" +.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan +.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned +.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +.\" License Agreement applies to this software. +.\" +.\" History: +.\" +.\" Written at NRL for OPIE 2.0. +.\" +.ll 6i +.pl 10.5i +.\" @(#)opieaccess.5 2.0 (NRL) 1/10/95 +.\" +.lt 6.0i +.TH OPIEACCESS 5 "January 10, 1995" +.AT 3 +.SH NAME +[/etc/]opieaccess \- OPIE database of trusted networks + +.SH DESCRIPTION +The +.I opieaccess +file contains a list of networks that are considered trusted by the system as +far as security against passive attacks is concerned. Users from networks so +trusted will be able to log in using OPIE responses, but not be required to +do so, while users from networks that are not trusted will always be required +to use OPIE responses (the default behavior). This trust allows a site to +have a more gentle migration to OPIE by allowing it to be non-mandatory for +"inside" networks while allowing users to choose whether they with to use OPIE +to protect their passwords or not. +.sp +The entire notion of trust implemented in the +.I opieaccess +file is a major security hole because it opens your system back up to the same +passive attacks that the OPIE system is designed to protect you against. The +.I opieaccess +support in this version of OPIE exists solely because we believe that it is +better to have it so that users who don't want their accounts broken into can +use OPIE than to have them prevented from doing so by users who don't want +to use OPIE. In any environment, it should be considered a transition tool and +not a permanent fixture. When it is not being used as a transition tool, a +version of OPIE that has been built without support for the +.I opieaccess +file should be built to prevent the possibility of an attacker using this file +as a means to circumvent the OPIE software. +.sp +The +.I opieaccess +file consists of lines containing three fields separated by spaces (tabs are +properly interpreted, but spaces should be used instead) as follows: +.PP +.nf +.ta \w' 'u +Field Description +action "permit" or "deny" non-OPIE logins +address Address of the network to match +mask Mask of the network to match +.fi + +Subnets can be controlled by using the appropriate address and mask. Individual +hosts can be controlled by using the appropriate address and a mask of +255.255.255.255. If no rules are matched, the default is to deny non-0PIE +logins. + +.SH SEE ALSO +.BR opie (4), +.BR opiekeys (5), +.BR opiepasswd (1), +.BR opieinfo (1), +.BR opiesu (1), +.BR opielogin (1), +.BR opieftpd (8) + +.SH AUTHOR +Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden +of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and +Craig Metz. + +S/Key is a trademark of Bell Communications Research (Bellcore). + +.SH CONTACT +OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join, +send an email request to: +.sp +skey-users-request@thumper.bellcore.com diff --git a/contrib/opie/opieftpd.8 b/contrib/opie/opieftpd.8 new file mode 100644 index 0000000..1943ce9 --- /dev/null +++ b/contrib/opie/opieftpd.8 @@ -0,0 +1,280 @@ +.\" opieftpd.8: Manual page describing the FTP daemon. +.\" +.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan +.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned +.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +.\" License Agreement applies to this software. +.\" +.\" History: +.\" +.\" Modified at NRL for OPIE 2.0. +.\" Originally from BSD. +.\" +.\" NOTE: +.\" +.\" This manual page uses the BSD >= Net/2 "mandoc" macros and may not +.\" format properly on all systems. +.\" +.\" Copyright (c) 1985, 1988, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)opieopieftpd.8 6.9 (Berkeley) 3/16/91 +.\" +.TH OPIEFTPD 8 "10 January 1995" + +.SH NAME +opieftpd \- File Transfer Protocol server that uses OPIE authentication + +.SH SYNOPSIS +.B opieftpd +[\-d] [\-l] [\-t +.I timeout +] [\-T +.I maxtimeout +] + +.SH DESCRIPTION +.I opieftpd +is the Internet File Transfer Protocol server process. The server uses the +TCP protocol and listens at the port specified in the ftp service +specification; see +.IR services (5). + +.SH OPTIONS +.TP +.B \-d +Debugging information is written to the system logs. +.TP +.B \-l +Each +.IR ftp (1) +session is logged in the system logs. +.TP +.B \-t +The inactivity timeout period is set to +.I timeout +seconds (the default is 15 minutes). +.TP +.B \-T +A client may also request a different timeout period; +the maximum period allowed may be set to +.I maxtimeout +seconds with the +.B \-T +option. The default limit is 2 hours. +.SH COMMANDS +The ftp server currently supports the following ftp +requests; case is not distinguished: +.PP +.nf +.ta \w'Request 'u +Request Description +ABOR abort previous command +ACCT specify account (ignored) +ALLO allocate storage (vacuously) +APPE append to a file +CDUP change to parent of current working directory +CWD change working directory +DELE delete a file +HELP give help information +LIST give a list of files in a directory +MKD make a directory +MDTM show last modification time of file +MODE specify data transfer mode +NLST give name list of files in directory +NOOP do nothing +PASS specify password +PASV prepare for server-to-server transfer +PORT specify data connection port +PWD print the current working directory +QUIT terminate session +REST restart incomplete transfer +RETR retrieve a file +RMD remove a directory +RNFR specify rename-from file name +RNTO specify rename-to file name +SITE non-standard commands (see next section) +SIZE return size of file +STAT return status of server +STOR store a file +STOU store a file with a unique name +STRU specify data transfer structure +SYST show operating system type of server system +TYPE specify data transfer type +USER specify user name +XCUP change to parent of current working directory (deprecated) +XCWD change working directory (deprecated) +XMKD make a directory (deprecated) +XPWD print the current working directory (deprecated) +XRMD remove a directory (deprecated) +.fi + +The following non-standard or UNIX-specific commands are supported +by the SITE request: +.PP +.nf +.ta \w'Request 'u +Request Description +UMASK change umask (e.g. SITE UMASK 002) +IDLE set idle-timer (e.g. SITE IDLE 60) +CHMOD change mode of a file (e.g. SITE CHMOD 755 file) +HELP give help information (e.g. SITE HELP) +.fi +.sp +The remaining ftp requests specified in Internet RFC-959 are +recognized, but not implemented. +.sp +MDTM and SIZE are not specified in RFC-959, but will appear +in the next updated FTP RFC. + +The ftp server will abort an active file transfer only when the +ABOR command is preceded by a Telnet "Interrupt Process" (IP) +signal and a Telnet "Synch" signal in the command Telnet stream, +as described in Internet RFC-959. +If a STAT command is received during a data transfer, preceded by +a Telnet IP and Synch, transfer status will be returned. +.I opieftpd +interprets file names according to the globbing conventions used by +.IR csh (1). +This allows users to utilize the metacharacters +\&*?[]{}~. +.sp +.I opieftpd +authenticates users according to three rules: +.sp +The user name must be in the password data base, +.I /etc/passwd, +and not have a null password. In this case, a password +must be provided by the client before any file operations +may be performed. +.sp +The user name must not appear in the file +.I /etc/ftpusers. +.sp +The user must have a standard shell returned by +.IR getusershell (3). +.sp +If the user name is +.I anonymous +or +.I ftp, +an anonymous ftp account must be present in the password +file (user +.I ftp ). +In this case, the user is allowed to log in by specifying any +password (by convention, this is given as the client host's name). + +In the last case, +.I opieftpd +takes special measures to restrict the client's access privileges. +The server performs a +.IR chroot (2) +command to the home directory of the +.I ftp +user. +In order that system security is not breached, it is recommended +that the +.I ftp +subtree be constructed with care; the following +rules are recommended: +.sp +.TP +.B ~ftp +Make the home directory owned by +.I ftp +and unwritable by anyone. +.TP +.B ~ftp/bin +Make this directory owned by the super-user and unwritable by +anyone. The program +.IR ls (1) +must be present to support the LIST command. This +program should have mode 111. +.TP +.B ~ftp/etc +Make this directory owned by the super-user and unwritable by +anyone. The files +.IR passwd (5) +and +.IR group (5) +must be present for the +.IR ls (1) +command to be able to produce owner names rather than numbers. +The password field in +.I passwd +is not used, and should not contain real encrypted passwords. +These files should be mode 444. +.TP +.B ~ftp/pub +Make this directory mode 777 and owned by +.I ftp. +Users should then place files which are to be accessible via the +anonymous account in this directory. +.SH SEE ALSO +.BR ftpd (8), +.BR ftp (1), +.BR opie (4), +.BR opiekey (1), +.BR opiepasswd (1), +.BR opieinfo (1), +.BR opiesu (1), +.BR opieftpd (8), +.BR opiekeys (5), +.BR opieaccess (5) + +.SH BUGS +The anonymous account is inherently dangerous and should +avoided when possible. In +.I opieftpd, +it is a compile-time option that should be disabled if it is not +being used. +The server must run as the super-user +to create sockets with privileged port numbers. It maintains +an effective user id of the logged in user, reverting to +the super-user only when binding addresses to sockets. The +possible security holes have been scrutinized, but are possibly incomplete. + +.SH HISTORY +The +.I ftpd +command appeared in 4.2BSD. + +.SH AUTHOR +Originally written for BSD, +.I ftpd +was modified at NRL by Randall Atkinson, Dan McDonald, and Craig Metz to +support OTP authentication. + +.SH CONTACT +OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join, +send an email request to: +.sp +skey-users-request@thumper.bellcore.com diff --git a/contrib/opie/opieftpd.c b/contrib/opie/opieftpd.c new file mode 100644 index 0000000..b11ece4 --- /dev/null +++ b/contrib/opie/opieftpd.c @@ -0,0 +1,1643 @@ +/* opieftpd.c: Main program for an FTP daemon. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Fixed the filename at the top. + Moved LS_COMMAND here. + Modified by cmetz for OPIE 2.2. Use FUNCTION definition et al. + Removed useless strings (I don't think that removing the + ucb copyright one is a problem -- please let me know if + I'm wrong). Changed default CMASK to 077. Removed random + comments. Use ANSI stdargs for reply/lreply if we can, + added stdargs version of reply/lreply. Don't declare the + tos variable unless IP_TOS defined. Include stdargs headers + early. More headers ifdefed. Made everything static. + Got rid of gethostname() call and use of hostname. Pared + down status response for places where header files frequently + cause trouble. Made logging of user logins (ala -l) + non-optional. Moved reply()/lrepy(). Fixed some prototypes. + Modified at NRL for OPIE 2.1. Added declaration of envp. Discard + result of opiechallenge (allows access control to work). + Added patches for AIX. Symbol changes for autoconf. + Modified at NRL for OPIE 2.01. Changed password lookup handling + to avoid problems with drain-bamaged shadow password packages. + Properly handle internal state for anonymous FTP. Unlock + user accounts properly if login fails because of /etc/shells. + Make sure to close syslog by function to avoid problems with + drain bamaged syslog implementations. + Modified at NRL for OPIE 2.0. + Originally from BSD Net/2. + + There is some really, really ugly code in here. +*/ +/* + * Copyright (c) 1985, 1988, 1990 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opie_cfg.h" + +#if HAVE_ANSISTDARG +#include +#endif /* HAVE_ANSISTDARG */ + +/* + * FTP server. + */ + +#if HAVE_SYS_PARAM_H +#include +#endif /* HAVE_SYS_PARAM_H */ +#include +/* #include */ +#include +#include +#ifdef SYS_FCNTL_H +#include +#else +#include +#endif /* SYS_FCNTL_H */ +#include + +#include +#include +#include + +#define FTP_NAMES +#include +#include +#include + +#include +#include +#include +#if HAVE_TIME_H +#include +#endif /* HAVE_TIME_H */ +#if HAVE_PWD_H +#include +#endif /* HAVE_PWD_H */ +#include +#include +#include +#include +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include +#include +#include +#include +#include + +#include "opie.h" + +#if HAVE_SHADOW_H +#include +#endif /* HAVE_SHADOW_H */ + +#if HAVE_CRYPT_H +#include +#endif /* HAVE_CRYPT_H */ + +#if HAVE_SYS_UTSNAME_H +#include +#endif /* HAVE_SYS_UTSNAME_H */ + +#ifdef _AIX +#include +#include +#endif /* _AIX */ + +#ifdef IP_TOS +#ifndef IPTOS_THROUGHPUT +#undef IP_TOS +#endif /* !IPTOS_THROUGHPUT */ +#ifndef IPTOS_LOWDELAY +#undef IP_TOS +#endif /* !IPTOS_LOWDELAY */ +#endif /* IP_TOS */ + +extern int errno; +extern char *home; /* pointer to home directory for glob */ +extern FILE *ftpd_popen __P((char *, char *)); +extern int ftpd_pclose __P((FILE *)); +extern char cbuf[]; +extern off_t restart_point; + +static struct sockaddr_in ctrl_addr; +static struct sockaddr_in data_source; +struct sockaddr_in data_dest; +struct sockaddr_in his_addr; +static struct sockaddr_in pasv_addr; + +static int data; +jmp_buf errcatch; +static jmp_buf urgcatch; +int logged_in; +struct passwd *pw; +int debug; +int timeout = 900; /* timeout after 15 minutes of inactivity */ +int maxtimeout = 7200; /* don't allow idle time to be set beyond 2 hours */ + +#if DOANONYMOUS +static int guest; +#endif /* DOANONYMOUS */ +int type; +int form; +static int stru; /* avoid C keyword */ +static int mode; +int usedefault = 1; /* for data transfers */ +int pdata = -1; /* for passive mode */ +static int transflag; +static off_t file_size; +static off_t byte_count; + +#if (!defined(CMASK) || CMASK == 0) +#undef CMASK +#define CMASK 077 +#endif + +static int defumask = CMASK; /* default umask value */ +char tmpline[7]; +char remotehost[MAXHOSTNAMELEN]; + +/* + * Timeout intervals for retrying connections + * to hosts that don't accept PORT cmds. This + * is a kludge, but given the problems with TCP... + */ +#define SWAITMAX 90 /* wait at most 90 seconds */ +#define SWAITINT 5 /* interval between retries */ + +static int swaitmax = SWAITMAX; +static int swaitint = SWAITINT; + +#if DOTITLE +static char **Argv = NULL; /* pointer to argument vector */ +static char *LastArgv = NULL; /* end of argv */ +static char proctitle[BUFSIZ]; /* initial part of title */ +#endif /* DOTITLE */ + +static int af_pwok = 0, pwok = 0; +static struct opie opiestate; + +VOIDRET perror_reply __P((int, char *)); +VOIDRET dologout __P((int)); +char *getline __P((char *, int, FILE *)); +VOIDRET upper __P((char *)); + +static VOIDRET lostconn __P((int)); +static FILE *getdatasock __P((char *)); +static FILE *dataconn __P((char *, off_t, char *)); +static int checkuser __P((char *)); +static VOIDRET end_login __P((void)); +static VOIDRET send_data __P((FILE *, FILE *, off_t)); +static int receive_data __P((FILE *, FILE *)); +static char *gunique __P((char *)); +static char *sgetsave __P((char *)); + +int logwtmp __P((char *, char *, char *)); + +int fclose __P((FILE *)); + +#ifdef HAVE_ANSISTDARG +VOIDRET reply FUNCTION((stdarg is ANSI only), int n AND char *fmt AND ...) +{ + va_list ap; + char buffer[1024]; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + printf("%d %s\r\n", n, buffer); + fflush(stdout); + if (debug) + syslog(LOG_DEBUG, "<--- %d %s", n, buffer); +} +#else /* HAVE_ANSISTDARG */ +VOIDRET reply FUNCTION((n, fmt, p0, p1, p2, p3, p4, p5), int n AND char *fmt AND int p0 AND int p1 AND int p2 AND int p3 AND int p4 AND int p5) +{ + printf("%d ", n); + printf(fmt, p0, p1, p2, p3, p4, p5); + printf("\r\n"); + fflush(stdout); + if (debug) { + syslog(LOG_DEBUG, "<--- %d ", n); + syslog(LOG_DEBUG, fmt, p0, p1, p2, p3, p4, p5); + } +} +#endif /* HAVE_ANSISTDARG */ + +#ifdef HAVE_ANSISTDARG +VOIDRET lreply FUNCTION((stdarg is ANSI only), int n AND char *fmt AND ...) +{ + va_list ap; + char buffer[1024]; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + printf("%d- %s\r\n", n, buffer); + fflush(stdout); + if (debug) + syslog(LOG_DEBUG, "<--- %d- %s", n, buffer); +} +#else /* HAVE_ANSISTDARG */ +VOIDRET lreply FUNCTION((n, fmt, p0, p1, p2, p3, p4, p5), int n AND char *fmt AND int p0 AND int p1 AND int p2 AND int p3 AND int p4 AND int p5) +{ + printf("%d- ", n); + printf(fmt, p0, p1, p2, p3, p4, p5); + printf("\r\n"); + fflush(stdout); + if (debug) { + syslog(LOG_DEBUG, "<--- %d- ", n); + syslog(LOG_DEBUG, fmt, p0, p1, p2, p3, p4, p5); + } +} +#endif /* HAVE_ANSISTDARG */ + +static VOIDRET lostconn FUNCTION((input), int input) +{ + if (debug) + syslog(LOG_DEBUG, "lost connection"); + dologout(-1); +} + +static char ttyline[20]; + +/* + * Helper function for sgetpwnam(). + */ +static char *sgetsave FUNCTION((s), char *s) +{ + char *new = malloc((unsigned) strlen(s) + 1); + + if (new == NULL) { + perror_reply(421, "Local resource failure: malloc"); + dologout(1); + /* NOTREACHED */ + } + strcpy(new, s); + return (new); +} + +/* + * Save the result of a getpwnam. Used for USER command, since + * the data returned must not be clobbered by any other command + * (e.g., globbing). + */ +static struct passwd *sgetpwnam FUNCTION((name), char *name) +{ + static struct passwd save; + register struct passwd *p; + +#if HAVE_SHADOW + struct spwd *spwd; +#endif /* HAVE_SHADOW */ + + if ((p = getpwnam(name)) == NULL) + return (p); + +#if HAVE_SHADOW + if ((spwd = getspnam(name)) == NULL) + return NULL; + + endspent(); + + p->pw_passwd = spwd->sp_pwdp; +#endif /* HAVE_SHADOW */ + + endpwent(); + + if (save.pw_name) { + free(save.pw_name); + free(save.pw_passwd); + free(save.pw_gecos); + free(save.pw_dir); + free(save.pw_shell); + } + save = *p; + save.pw_name = sgetsave(p->pw_name); + save.pw_passwd = sgetsave(p->pw_passwd); + save.pw_gecos = sgetsave(p->pw_gecos); + save.pw_dir = sgetsave(p->pw_dir); + save.pw_shell = sgetsave(p->pw_shell); + return (&save); +} + +int login_attempts; /* number of failed login attempts */ +int askpasswd; /* had user command, ask for passwd */ + +/* + * USER command. + * Sets global passwd pointer pw if named account exists and is acceptable; + * sets askpasswd if a PASS command is expected. If logged in previously, + * need to reset state. If name is "ftp" or "anonymous", the name is not in + * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return. + * If account doesn't exist, ask for passwd anyway. Otherwise, check user + * requesting login privileges. Disallow anyone who does not have a standard + * shell as returned by getusershell(). Disallow anyone mentioned in the file + * _PATH_FTPUSERS to allow people such as root and uucp to be avoided. + */ +int user FUNCTION((name), char *name) +{ + register char *cp; + char *shell; + + if (logged_in) { +#if DOANONYMOUS + if (guest) { + reply(530, "Can't change user from guest login."); + return -1; + } +#endif /* DOANONMOUS */ + end_login(); + } + askpasswd = 1; +#if DOANONYMOUS + guest = 0; + if (!strcmp(name, "ftp") || !strcmp(name, "anonymous")) + if (!checkuser("ftp") && !checkuser("anonymous")) + if ((pw = sgetpwnam("ftp")) != NULL) { + guest = 1; + askpasswd = 1; + reply(331, "Guest login ok, send ident as password."); + syslog(LOG_INFO, "Anonymous FTP connection made from host %s.", + remotehost); + return 0; + } +#endif /* DOANONYMOUS */ + if (pw = sgetpwnam(name)) { + if ((shell = pw->pw_shell) == NULL || *shell == 0) + shell = _PATH_BSHELL; + while ((cp = getusershell()) != NULL) + if (!strcmp(cp, shell)) + break; + endusershell(); + if (cp == NULL || checkuser(name) || + ((pw->pw_passwd[0] == '*') || (pw->pw_passwd[0] == '#'))) { +#if DEBUG + if (!cp) + syslog(LOG_DEBUG, "Couldn't find %s in the list of valid shells.", pw->pw_shell); + if (checkuser(name)) + syslog(LOG_DEBUG, "checkuser failed - user in /etc/ftpusers?"); + if (((pw->pw_passwd[0] == '*') || (pw->pw_passwd[0] == '#'))) + syslog(LOG_DEBUG, "Login disabled: pw_passwd == %s", pw->pw_passwd); +#endif /* DEBUG */ + pw = (struct passwd *) NULL; + askpasswd = -1; + } + } + { + char prompt[OPIE_CHALLENGE_MAX + 1]; + + opiechallenge(&opiestate, name, prompt); + + if (askpasswd == -1) { + syslog(LOG_WARNING, "Invalid FTP user name %s attempted from %s.", name, remotehost); + pwok = 0; + } else + pwok = af_pwok && opiealways(pw->pw_dir); + +#if NEW_PROMPTS + reply(331, "Response to %s %s for %s.", prompt, +#else /* NEW_PROMPTS */ + reply(331, "OTP response %s %s for %s.", prompt, +#endif /* NEW_PROMPTS */ + pwok ? "requested" : "required", name); + } + /* Delay before reading passwd after first failed attempt to slow down + passwd-guessing programs. */ + if (login_attempts) + sleep((unsigned) login_attempts); + + return 0; +} + +/* + * Check if a user is in the file _PATH_FTPUSERS + */ +static int checkuser FUNCTION((name), char *name) +{ + register FILE *fd; + register char *p; + char line[BUFSIZ]; + + if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) + if ((p = strchr(line, '\n')) != NULL) { + *p = '\0'; + if (line[0] == '#') + continue; + if (strcmp(line, name) == 0) + return (1); + } + fclose(fd); + } + return (0); +} + +/* + * Terminate login as previous user, if any, resetting state; + * used when USER command is given or login fails. + */ +static VOIDRET end_login FUNCTION_NOARGS +{ + if (seteuid((uid_t) 0)) + syslog(LOG_ERR, "Can't set euid"); + if (logged_in) + logwtmp(ttyline, "", ""); + pw = NULL; + logged_in = 0; +#if DOANONYMOUS + guest = 0; +#endif /* DOANONYMOUS */ +} + +VOIDRET pass FUNCTION((passwd), char *passwd) +{ + int legit = askpasswd + 1, i; + + if (logged_in || askpasswd == 0) { + reply(503, "Login with USER first."); + return; + } + askpasswd = 0; + +#if DOANONYMOUS + if (!guest) { /* "ftp" is only account allowed no password */ +#endif /* DOANONYMOUS */ + i = opieverify(&opiestate, passwd); + if (legit && i && pwok) + i = strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd); + if (!legit || i) { + reply(530, "Login incorrect."); + pw = NULL; + if (login_attempts++ >= 5) { + syslog(LOG_WARNING, + "Repeated login failures for user %s from %s", + pw->pw_name, remotehost); + exit(0); + } + return; + } +#if DOANONYMOUS + } +#endif /* DOANONYMOUS */ + login_attempts = 0; /* this time successful */ + setegid((gid_t) pw->pw_gid); + initgroups(pw->pw_name, pw->pw_gid); + + /* open wtmp before chroot */ + sprintf(ttyline, "ftp%d", getpid()); + logwtmp(ttyline, pw->pw_name, remotehost); + logged_in = 1; + +#if DOANONYMOUS + if (guest) { + /* We MUST do a chdir() after the chroot. Otherwise the old current + directory will be accessible as "." outside the new root! */ + if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { + reply(550, "Can't set guest privileges."); + goto bad; + } + } else +#endif /* DOANONYMOUS */ + if (chdir(pw->pw_dir) < 0) { + if (chdir("/") < 0) { + reply(530, "User %s: can't change directory to %s.", + pw->pw_name, pw->pw_dir); + goto bad; + } else + lreply(230, "No directory! Logging in with home=/"); + } +/* This patch was contributed by an OPIE user. We don't know what it + does, exactly. It may or may not work. */ +#ifdef _AIX + { + priv_t priv; + priv.pv_priv[0] = 0; + priv.pv_priv[1] = 0; + setgroups(NULL, NULL); + if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_EFFECTIVE|PRIV_BEQUEATH, + &priv, sizeof(priv_t)) < 0 || + setgidx(ID_REAL|ID_EFFECTIVE, (gid_t)pw->pw_gid) < 0 || + setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)pw->pw_uid) < 0 || + seteuid((uid_t)pw->pw_uid) < 0) { + reply(550, "Can't set uid (_AIX3)."); + goto bad; + } + } +#else /* _AIX */ + if (seteuid((uid_t) pw->pw_uid) < 0) { + reply(550, "Can't set uid."); + goto bad; + } +#endif /* _AIX */ +#if DOANONYMOUS + if (guest) { + reply(230, "Guest login ok, access restrictions apply."); +#if DOTITLE + sprintf(proctitle, "%s: anonymous/%.*s", remotehost, + sizeof(proctitle) - sizeof(remotehost) - + sizeof(": anonymous/"), passwd); + setproctitle(proctitle); +#endif /* DOTITLE */ + syslog(LOG_NOTICE, "ANONYMOUS FTP login from %s with ID %s", + remotehost, passwd); + } else +#endif /* DOANONYMOUS */ + { + reply(230, "User %s logged in.", pw->pw_name); + +#if DOTITLE + sprintf(proctitle, "%s: %s", remotehost, pw->pw_name); + setproctitle(proctitle); +#endif /* DOTITLE */ + syslog(LOG_NOTICE, "FTP login from %s with user name %s", + remotehost, pw->pw_name); + } + home = pw->pw_dir; /* home dir for globbing */ + umask(defumask); + return; + +bad: + /* Forget all about it... */ + end_login(); +} + +VOIDRET retrieve FUNCTION((cmd, name), char *cmd AND char *name) +{ + FILE *fin, *dout; + struct stat st; + int (*closefunc) (); + + if (cmd == 0) { + fin = fopen(name, "r"), closefunc = fclose; + st.st_size = 0; + } else { + char line[BUFSIZ]; + + sprintf(line, cmd, name), name = line; + fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; + st.st_size = -1; +#if HAVE_ST_BLKSIZE + st.st_blksize = BUFSIZ; +#endif /* HAVE_ST_BLKSIZE */ + } + if (fin == NULL) { + if (errno != 0) + perror_reply(550, name); + return; + } + if (cmd == 0 && + (fstat(fileno(fin), &st) < 0 || (st.st_mode & S_IFMT) != S_IFREG)) { + reply(550, "%s: not a plain file.", name); + goto done; + } + if (restart_point) { + if (type == TYPE_A) { + register int i, n, c; + + n = restart_point; + i = 0; + while (i++ < n) { + if ((c = getc(fin)) == EOF) { + perror_reply(550, name); + goto done; + } + if (c == '\n') + i++; + } + } else + if (lseek(fileno(fin), restart_point, SEEK_SET /* L_SET */ ) < 0) { + perror_reply(550, name); + goto done; + } + } + dout = dataconn(name, st.st_size, "w"); + if (dout == NULL) + goto done; +#if HAVE_ST_BLKSIZE + send_data(fin, dout, st.st_blksize); +#else /* HAVE_ST_BLKSIZE */ + send_data(fin, dout, BUFSIZ); +#endif /* HAVE_ST_BLKSIZE */ + fclose(dout); + data = -1; + pdata = -1; +done: + (*closefunc) (fin); +} + +VOIDRET store FUNCTION((name, mode, unique), char *name AND char *mode AND int unique) +{ + FILE *fout, *din; + struct stat st; + int (*closefunc) (); + + if (unique && stat(name, &st) == 0 && + (name = gunique(name)) == NULL) + return; + + if (restart_point) + mode = "r+w"; + fout = fopen(name, mode); + closefunc = fclose; + if (fout == NULL) { + perror_reply(553, name); + return; + } + if (restart_point) { + if (type == TYPE_A) { + register int i, n, c; + + n = restart_point; + i = 0; + while (i++ < n) { + if ((c = getc(fout)) == EOF) { + perror_reply(550, name); + goto done; + } + if (c == '\n') + i++; + } + /* We must do this seek to "current" position because we are changing + from reading to writing. */ + if (fseek(fout, 0L, SEEK_CUR /* L_INCR */ ) < 0) { + perror_reply(550, name); + goto done; + } + } else + if (lseek(fileno(fout), restart_point, SEEK_SET /* L_SET */ ) < 0) { + perror_reply(550, name); + goto done; + } + } + din = dataconn(name, (off_t) - 1, "r"); + if (din == NULL) + goto done; + if (receive_data(din, fout) == 0) { + if (unique) + reply(226, "Transfer complete (unique file name:%s).", + name); + else + reply(226, "Transfer complete."); + } + fclose(din); + data = -1; + pdata = -1; +done: + (*closefunc) (fout); +} + +static FILE *getdatasock FUNCTION((mode), char *mode) +{ + int s, on = 1, tries; + + if (data >= 0) + return (fdopen(data, mode)); + if (seteuid((uid_t) 0)) + syslog(LOG_ERR, "Can't set euid"); + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) + goto bad; + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + (char *) &on, sizeof(on)) < 0) + goto bad; + /* anchor socket to avoid multi-homing problems */ + data_source.sin_family = AF_INET; + data_source.sin_addr = ctrl_addr.sin_addr; + for (tries = 1;; tries++) { + if (bind(s, (struct sockaddr *) & data_source, + sizeof(data_source)) >= 0) + break; + if (errno != EADDRINUSE || tries > 10) + goto bad; + sleep(tries); + } + if (seteuid((uid_t) pw->pw_uid)) + syslog(LOG_ERR, "Can't set euid"); +#ifdef IP_TOS + on = IPTOS_THROUGHPUT; + if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *) &on, sizeof(int)) < 0) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); +#endif + return (fdopen(s, mode)); +bad: + if (seteuid((uid_t) pw->pw_uid)) + syslog(LOG_ERR, "Can't set euid"); + close(s); + return (NULL); +} + +static FILE *dataconn FUNCTION((name, size, mode), char *name AND off_t size AND char *mode) +{ + char sizebuf[32]; + FILE *file; + int retry = 0; +#ifdef IP_TOS + int tos; +#endif /* IP_TOS */ + + file_size = size; + byte_count = 0; + if (size != (off_t) - 1) + sprintf(sizebuf, " (%ld bytes)", size); + else + strcpy(sizebuf, ""); + if (pdata >= 0) { + struct sockaddr_in from; + int s, fromlen = sizeof(from); + + s = accept(pdata, (struct sockaddr *) & from, &fromlen); + if (s < 0) { + reply(425, "Can't open data connection."); + close(pdata); + pdata = -1; + return (NULL); + } + close(pdata); + pdata = s; +#ifdef IP_TOS + tos = IPTOS_LOWDELAY; + setsockopt(s, IPPROTO_IP, IP_TOS, (char *) &tos, + sizeof(int)); + +#endif + reply(150, "Opening %s mode data connection for %s%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + return (fdopen(pdata, mode)); + } + if (data >= 0) { + reply(125, "Using existing data connection for %s%s.", + name, sizebuf); + usedefault = 1; + return (fdopen(data, mode)); + } + if (usedefault) + data_dest = his_addr; + usedefault = 1; + file = getdatasock(mode); + if (file == NULL) { + reply(425, "Can't create data socket (%s,%d): %s.", + inet_ntoa(data_source.sin_addr), + ntohs(data_source.sin_port), strerror(errno)); + return (NULL); + } + data = fileno(file); + while (connect(data, (struct sockaddr *) & data_dest, + sizeof(data_dest)) < 0) { + if (errno == EADDRINUSE && retry < swaitmax) { + sleep((unsigned) swaitint); + retry += swaitint; + continue; + } + perror_reply(425, "Can't build data connection"); + fclose(file); + data = -1; + return (NULL); + } + reply(150, "Opening %s mode data connection for %s%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + return (file); +} + +/* + * Tranfer the contents of "instr" to + * "outstr" peer using the appropriate + * encapsulation of the data subject + * to Mode, Structure, and Type. + * + * NB: Form isn't handled. + */ +static VOIDRET send_data FUNCTION((instr, outstr, blksize), FILE *instr AND FILE *outstr AND off_t blksize) +{ + register int c, cnt; + register char *buf; + int netfd, filefd; + + transflag++; + if (setjmp(urgcatch)) { + transflag = 0; + return; + } + switch (type) { + + case TYPE_A: + while ((c = getc(instr)) != EOF) { + byte_count++; + if (c == '\n') { + if (ferror(outstr)) + goto data_err; + putc('\r', outstr); + } + putc(c, outstr); + } + fflush(outstr); + transflag = 0; + if (ferror(instr)) + goto file_err; + if (ferror(outstr)) + goto data_err; + reply(226, "Transfer complete."); + return; + + case TYPE_I: + case TYPE_L: + if ((buf = malloc((u_int) blksize)) == NULL) { + transflag = 0; + perror_reply(451, "Local resource failure: malloc"); + return; + } + netfd = fileno(outstr); + filefd = fileno(instr); + while ((cnt = read(filefd, buf, (u_int) blksize)) > 0 && + write(netfd, buf, cnt) == cnt) + byte_count += cnt; + transflag = 0; + free(buf); + if (cnt != 0) { + if (cnt < 0) + goto file_err; + goto data_err; + } + reply(226, "Transfer complete."); + return; + default: + transflag = 0; + reply(550, "Unimplemented TYPE %d in send_data", type); + return; + } + +data_err: + transflag = 0; + perror_reply(426, "Data connection"); + return; + +file_err: + transflag = 0; + perror_reply(551, "Error on input file"); +} + +/* + * Transfer data from peer to + * "outstr" using the appropriate + * encapulation of the data subject + * to Mode, Structure, and Type. + * + * N.B.: Form isn't handled. + */ +static int receive_data FUNCTION((instr, outstr), FILE *instr AND FILE *outstr) +{ + register int c; + int cnt, bare_lfs = 0; + char buf[BUFSIZ]; + + transflag++; + if (setjmp(urgcatch)) { + transflag = 0; + return (-1); + } + switch (type) { + + case TYPE_I: + case TYPE_L: + while ((cnt = read(fileno(instr), buf, sizeof buf)) > 0) { + if (write(fileno(outstr), buf, cnt) != cnt) + goto file_err; + byte_count += cnt; + } + if (cnt < 0) + goto data_err; + transflag = 0; + return (0); + + case TYPE_E: + reply(553, "TYPE E not implemented."); + transflag = 0; + return (-1); + + case TYPE_A: + while ((c = getc(instr)) != EOF) { + byte_count++; + if (c == '\n') + bare_lfs++; + while (c == '\r') { + if (ferror(outstr)) + goto data_err; + if ((c = getc(instr)) != '\n') { + putc('\r', outstr); + if (c == '\0' || c == EOF) + goto contin2; + } + } + putc(c, outstr); + contin2:; + } + fflush(outstr); + if (ferror(instr)) + goto data_err; + if (ferror(outstr)) + goto file_err; + transflag = 0; + if (bare_lfs) { + lreply(230, "WARNING! %d bare linefeeds received in ASCII mode", bare_lfs); + printf(" File may not have transferred correctly.\r\n"); + } + return (0); + default: + reply(550, "Unimplemented TYPE %d in receive_data", type); + transflag = 0; + return (-1); + } + +data_err: + transflag = 0; + perror_reply(426, "Data Connection"); + return (-1); + +file_err: + transflag = 0; + perror_reply(452, "Error writing file"); + return (-1); +} + +VOIDRET statfilecmd FUNCTION((filename), char *filename) +{ + char line[BUFSIZ]; + FILE *fin; + int c; + +#if HAVE_LS_G_FLAG + sprintf(line, "%s %s", "/bin/ls -lgA", filename); +#else /* HAVE_LS_G_FLAG */ + sprintf(line, "%s %s", "/bin/ls -lA", filename); +#endif /* HAVE_LS_G_FLAG */ + fin = ftpd_popen(line, "r"); + lreply(211, "status of %s:", filename); + while ((c = getc(fin)) != EOF) { + if (c == '\n') { + if (ferror(stdout)) { + perror_reply(421, "control connection"); + ftpd_pclose(fin); + dologout(1); + /* NOTREACHED */ + } + if (ferror(fin)) { + perror_reply(551, filename); + ftpd_pclose(fin); + return; + } + putc('\r', stdout); + } + putc(c, stdout); + } + ftpd_pclose(fin); + reply(211, "End of Status"); +} + +VOIDRET statcmd FUNCTION_NOARGS +{ +/* COMMENTED OUT STUFF BECAUSE THINGS BROKE ON SUNOS. */ + struct sockaddr_in *sin; + u_char *a, *p; + + lreply(211, "FTP server status:"); + printf(" \r\n"); + printf(" Connected to %s", remotehost); + if (!isdigit(remotehost[0])) + printf(" (%s)", inet_ntoa(his_addr.sin_addr)); + printf("\r\n"); + if (logged_in) { +#if DOANONYMOUS + if (guest) + printf(" Logged in anonymously\r\n"); + else +#endif /* DOANONYMOUS */ + printf(" Logged in as %s\r\n", pw->pw_name); + } else + if (askpasswd) + printf(" Waiting for password\r\n"); + else + printf(" Waiting for user name\r\n"); + if (data != -1) + printf(" Data connection open\r\n"); + else + if (pdata != -1) { + printf(" in Passive mode"); + sin = &pasv_addr; + goto printaddr; + } else + if (usedefault == 0) { + printf(" PORT"); + sin = &data_dest; + printaddr: + a = (u_char *) & sin->sin_addr; + p = (u_char *) & sin->sin_port; +#define UC(b) (((int) b) & 0xff) + printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]), + UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); +#undef UC + } else + printf(" No data connection\r\n"); + reply(211, "End of status"); +} + +VOIDRET opiefatal FUNCTION((s), char *s) +{ + reply(451, "Error in server: %s\n", s); + reply(221, "Closing connection due to server error."); + dologout(0); + /* NOTREACHED */ +} + +static VOIDRET ack FUNCTION((s), char *s) +{ + reply(250, "%s command successful.", s); +} + +VOIDRET nack FUNCTION((s), char *s) +{ + reply(502, "%s command not implemented.", s); +} + +VOIDRET yyerror FUNCTION((s), char *s) +{ + char *cp; + + if (cp = strchr(cbuf, '\n')) + *cp = '\0'; + reply(500, "'%s': command not understood.", cbuf); +} + +VOIDRET delete FUNCTION((name), char *name) +{ + struct stat st; + + if (stat(name, &st) < 0) { + perror_reply(550, name); + return; + } + if ((st.st_mode & S_IFMT) == S_IFDIR) { + if (rmdir(name) < 0) { + perror_reply(550, name); + return; + } + goto done; + } + if (unlink(name) < 0) { + perror_reply(550, name); + return; + } +done: + ack("DELE"); +} + +VOIDRET cwd FUNCTION((path), char *path) +{ + if (chdir(path) < 0) + perror_reply(550, path); + else + ack("CWD"); +} + +VOIDRET makedir FUNCTION((name), char *name) +{ + if (mkdir(name, 0777) < 0) + perror_reply(550, name); + else + reply(257, "MKD command successful."); +} + +VOIDRET removedir FUNCTION((name), char *name) +{ + if (rmdir(name) < 0) + perror_reply(550, name); + else + ack("RMD"); +} + +VOIDRET pwd FUNCTION_NOARGS +{ + char path[MAXPATHLEN + 1]; + + if (getcwd(path, MAXPATHLEN) == (char *) NULL) + reply(550, "%s.", path); + else + reply(257, "\"%s\" is current directory.", path); +} + +char *renamefrom FUNCTION((name), char *name) +{ + struct stat st; + + if (stat(name, &st) < 0) { + perror_reply(550, name); + return ((char *) 0); + } + reply(350, "File exists, ready for destination name"); + return (name); +} + +VOIDRET renamecmd FUNCTION((from, to), char *from AND char *to) +{ + if (rename(from, to) < 0) + perror_reply(550, "rename"); + else + ack("RNTO"); +} + +static VOIDRET dolog FUNCTION((sin), struct sockaddr_in *sin) +{ + struct hostent *hp = gethostbyaddr((char *) &sin->sin_addr, + sizeof(struct in_addr), AF_INET); + time_t t, time(); + + if (hp) + strncpy(remotehost, hp->h_name, sizeof(remotehost)); + else + strncpy(remotehost, inet_ntoa(sin->sin_addr), sizeof(remotehost)); +#if DOTITLE + sprintf(proctitle, "%s: connected", remotehost); + setproctitle(proctitle); +#endif /* DOTITLE */ + + t = time((time_t *) 0); + syslog(LOG_INFO, "connection from %s at %s", + remotehost, ctime(&t)); +} + +/* + * Record logout in wtmp file + * and exit with supplied status. + */ +VOIDRET dologout FUNCTION((status), int status) +{ + if (logged_in) { + if (seteuid((uid_t) 0)) + syslog(LOG_ERR, "Can't set euid"); + logwtmp(ttyline, "", ""); + } + /* beware of flushing buffers after a SIGPIPE */ + _exit(status); +} + +static VOIDRET myoob FUNCTION((input), int input) +{ + char *cp; + + /* only process if transfer occurring */ + if (!transflag) + return; + cp = tmpline; + if (getline(cp, 7, stdin) == NULL) { + reply(221, "You could at least say goodbye."); + dologout(0); + } + upper(cp); + if (strcmp(cp, "ABOR\r\n") == 0) { + tmpline[0] = '\0'; + reply(426, "Transfer aborted. Data connection closed."); + reply(226, "Abort successful"); + longjmp(urgcatch, 1); + } + if (strcmp(cp, "STAT\r\n") == 0) { + if (file_size != (off_t) - 1) + reply(213, "Status: %lu of %lu bytes transferred", + byte_count, file_size); + else + reply(213, "Status: %lu bytes transferred", byte_count); + } +} + +/* + * Note: a response of 425 is not mentioned as a possible response to + * the PASV command in RFC959. However, it has been blessed as + * a legitimate response by Jon Postel in a telephone conversation + * with Rick Adams on 25 Jan 89. + */ +VOIDRET passive FUNCTION_NOARGS +{ + int len; + register char *p, *a; + + pdata = socket(AF_INET, SOCK_STREAM, 0); + if (pdata < 0) { + perror_reply(425, "Can't open passive connection"); + return; + } + pasv_addr = ctrl_addr; + pasv_addr.sin_port = 0; + if (seteuid((uid_t) 0)) + syslog(LOG_ERR, "Can't set euid"); + if (bind(pdata, (struct sockaddr *) & pasv_addr, sizeof(pasv_addr)) < 0) { + seteuid((uid_t) pw->pw_uid); + goto pasv_error; + } + if (seteuid((uid_t) pw->pw_uid)) + syslog(LOG_ERR, "Can't set euid"); + len = sizeof(pasv_addr); + if (getsockname(pdata, (struct sockaddr *) & pasv_addr, &len) < 0) + goto pasv_error; + if (listen(pdata, 1) < 0) + goto pasv_error; + a = (char *) &pasv_addr.sin_addr; + p = (char *) &pasv_addr.sin_port; + +#define UC(b) (((int) b) & 0xff) + + reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), + UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); + return; + +pasv_error: + close(pdata); + pdata = -1; + perror_reply(425, "Can't open passive connection"); + return; +} + +/* + * Generate unique name for file with basename "local". + * The file named "local" is already known to exist. + * Generates failure reply on error. + */ +static char *gunique FUNCTION((local), char *local) +{ + static char new[MAXPATHLEN]; + struct stat st; + char *cp = strrchr(local, '/'); + int count = 0; + + if (cp) + *cp = '\0'; + if (stat(cp ? local : ".", &st) < 0) { + perror_reply(553, cp ? local : "."); + return ((char *) 0); + } + if (cp) + *cp = '/'; + strcpy(new, local); + cp = new + strlen(new); + *cp++ = '.'; + for (count = 1; count < 100; count++) { + sprintf(cp, "%d", count); + if (stat(new, &st) < 0) + return (new); + } + reply(452, "Unique file name cannot be created."); + return ((char *) 0); +} + +/* + * Format and send reply containing system error number. + */ +VOIDRET perror_reply FUNCTION((code, string), int code AND char *string) +{ + reply(code, "%s: %s.", string, strerror(errno)); +} + +static char *onefile[] = +{ + "", + 0 +}; + +VOIDRET send_file_list FUNCTION((whichfiles), char *whichfiles) +{ + struct stat st; + DIR *dirp = NULL; + struct dirent *dir; + FILE *dout = NULL; + register char **dirlist, *dirname; + int simple = 0; + + if (strpbrk(whichfiles, "~{[*?") != NULL) { + extern char **ftpglob(), *globerr; + + globerr = NULL; + dirlist = ftpglob(whichfiles); + if (globerr != NULL) { + reply(550, globerr); + return; + } else + if (dirlist == NULL) { + errno = ENOENT; + perror_reply(550, whichfiles); + return; + } + } else { + onefile[0] = whichfiles; + dirlist = onefile; + simple = 1; + } + + if (setjmp(urgcatch)) { + transflag = 0; + return; + } + while (dirname = *dirlist++) { + if (stat(dirname, &st) < 0) { + /* If user typed "ls -l", etc, and the client used NLST, do what the + user meant. */ + if (dirname[0] == '-' && *dirlist == NULL && + transflag == 0) { + retrieve("/bin/ls %s", dirname); + return; + } + perror_reply(550, whichfiles); + if (dout != NULL) { + fclose(dout); + transflag = 0; + data = -1; + pdata = -1; + } + return; + } + if ((st.st_mode & S_IFMT) == S_IFREG) { + if (dout == NULL) { + dout = dataconn("file list", (off_t) - 1, "w"); + if (dout == NULL) + return; + transflag++; + } + fprintf(dout, "%s%s\n", dirname, + type == TYPE_A ? "\r" : ""); + byte_count += strlen(dirname) + 1; + continue; + } else + if ((st.st_mode & S_IFMT) != S_IFDIR) + continue; + + if ((dirp = opendir(dirname)) == NULL) + continue; + + while ((dir = readdir(dirp)) != NULL) { + char nbuf[MAXPATHLEN]; + + if (dir->d_name[0] == '.' && (strlen(dir->d_name) == 1)) + continue; + if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && + (strlen(dir->d_name) == 2)) + continue; + + sprintf(nbuf, "%s/%s", dirname, dir->d_name); + + /* We have to do a stat to insure it's not a directory or special file. */ + if (simple || (stat(nbuf, &st) == 0 && + (st.st_mode & S_IFMT) == S_IFREG)) { + if (dout == NULL) { + dout = dataconn("file list", (off_t) - 1, "w"); + if (dout == NULL) + return; + transflag++; + } + if (nbuf[0] == '.' && nbuf[1] == '/') + fprintf(dout, "%s%s\n", &nbuf[2], + type == TYPE_A ? "\r" : ""); + else + fprintf(dout, "%s%s\n", nbuf, + type == TYPE_A ? "\r" : ""); + byte_count += strlen(nbuf) + 1; + } + } + closedir(dirp); + } + + if (dout == NULL) + reply(550, "No files found."); + else + if (ferror(dout) != 0) + perror_reply(550, "Data connection"); + else + reply(226, "Transfer complete."); + + transflag = 0; + if (dout != NULL) + fclose(dout); + data = -1; + pdata = -1; +} + +#if DOTITLE +/* + * clobber argv so ps will show what we're doing. + * (stolen from sendmail) + * warning, since this is usually started from inetd.conf, it + * often doesn't have much of an environment or arglist to overwrite. + */ +VOIDRET setproctitle FUNCTION((fmt, a, b, c), char *fmt AND int a AND int b AND int c) +{ + register char *p, *bp, ch; + register int i; + char buf[BUFSIZ]; + + sprintf(buf, fmt, a, b, c); + + /* make ps print our process name */ + p = Argv[0]; + *p++ = '-'; + + i = strlen(buf); + if (i > LastArgv - p - 2) { + i = LastArgv - p - 2; + buf[i] = '\0'; + } + bp = buf; + while (ch = *bp++) + if (ch != '\n' && ch != '\r') + *p++ = ch; + while (p < LastArgv) + *p++ = ' '; +} +#endif /* DOTITLE */ + +void catchexit FUNCTION_NOARGS +{ + closelog(); +} + +int main FUNCTION((argc, argv, envp), int argc AND char *argv[] AND char *envp[]) +{ + int addrlen, on = 1; + char *cp; +#ifdef IP_TOS + int tos; +#endif /* IP_TOS */ + + { + int i; + + for (i = sysconf(_SC_OPEN_MAX); i > 2; i--) + close(i); + } + + /* LOG_NDELAY sets up the logging connection immediately, necessary for + anonymous ftp's that chroot and can't do it later. */ + openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_DAEMON); + atexit(catchexit); + addrlen = sizeof(his_addr); + if (getpeername(0, (struct sockaddr *) & his_addr, &addrlen) < 0) { + syslog(LOG_ERR, "getpeername (%s): %m", argv[0]); + exit(1); + } + addrlen = sizeof(ctrl_addr); + if (getsockname(0, (struct sockaddr *) & ctrl_addr, &addrlen) < 0) { + syslog(LOG_ERR, "getsockname (%s): %m", argv[0]); + exit(1); + } +#ifdef IP_TOS + tos = IPTOS_LOWDELAY; + if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); +#endif + data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); + debug = 0; +#if DOTITLE + /* Save start and extent of argv for setproctitle. */ + Argv = argv; + while (*envp) + envp++; + LastArgv = envp[-1] + strlen(envp[-1]); +#endif /* DOTITLE */ + + argc--, argv++; + while (argc > 0 && *argv[0] == '-') { + for (cp = &argv[0][1]; *cp; cp++) + switch (*cp) { + + case 'v': + debug = 1; + break; + + case 'd': + debug = 1; + break; + + case 'l': + break; + + case 't': + timeout = atoi(++cp); + if (maxtimeout < timeout) + maxtimeout = timeout; + goto nextopt; + + case 'T': + maxtimeout = atoi(++cp); + if (timeout > maxtimeout) + timeout = maxtimeout; + goto nextopt; + + case 'u': + { + int val = 0; + + while (*++cp && *cp >= '0' && *cp <= '9') + val = val * 8 + *cp - '0'; + if (*cp) + fprintf(stderr, "ftpd: Bad value for -u\n"); + else + defumask = val; + goto nextopt; + } + + default: + fprintf(stderr, "ftpd: Unknown flag -%c ignored.\n", + *cp); + break; + } +nextopt: + argc--, argv++; + } + freopen(_PATH_DEVNULL, "w", stderr); + signal(SIGPIPE, lostconn); + signal(SIGCHLD, SIG_IGN); + if ((int) signal(SIGURG, myoob) < 0) + syslog(LOG_ERR, "signal: %m"); + + /* Try to handle urgent data inline */ +#ifdef SO_OOBINLINE + if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof(on)) < 0) + syslog(LOG_ERR, "setsockopt: %m"); +#endif + +#ifdef F_SETOWN + if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) + syslog(LOG_ERR, "fcntl F_SETOWN: %m"); +#endif + dolog(&his_addr); + /* Set up default state */ + data = -1; + type = TYPE_A; + form = FORM_N; + stru = STRU_F; + mode = MODE_S; + tmpline[0] = '\0'; + af_pwok = opieaccessfile(remotehost); + +#if 0 + { + struct utsname utsname; + + if (uname(&utsname) < 0) { + syslog(LOG_ERR, "uname() failed: %s", strerror(errno)); + exit(1); + } + + reply(220, "%s FTP server ready.", utsname.nodename); + } +#else /* 0 */ + reply(220, "FTP server ready."); +#endif /* 0 */ + + setjmp(errcatch); + for (;;) + yyparse(); + /* NOTREACHED */ + return 0; +} diff --git a/contrib/opie/opiegen.1 b/contrib/opie/opiegen.1 new file mode 100644 index 0000000..7dc1dfd --- /dev/null +++ b/contrib/opie/opiegen.1 @@ -0,0 +1,88 @@ +.\" opiegen.1: Manual page for the opiegen(1) program. +.\" +.\" %%% portions-copyright-cmetz +.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights +.\" Reserved. The Inner Net License Version 2 applies to these portions of +.\" the software. +.\" You should have received a copy of the license with this software. If +.\" you didn't get a copy, you may request one from . +.\" +.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan +.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned +.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +.\" License Agreement applies to this software. +.\" +.\" History: +.\" +.\" Created by cmetz for OPIE 2.2 from opiekey.1. +.\" +.ll 6i +.pl 10.5i +.lt 6.0i +.TH OPIEKEY 1 "February 20, 1996" +.AT 3 +.SH NAME +opiegen \- Example OPIE-based OTP generator + +.SH SYNOPSIS +.B opiegen +.sp 0 +[ +.I challenge +] +.sp 0 + +.SH DESCRIPTION +.I opiegen +takes a properly formed OTP challenge either from the command line or from +standard input, prompts the user for a secret pass phrase, and generates an +OTP response to that challenge. It is intended as an example for programmers +of how a simple OTP generator can be built. Users should probably use the +.I opiekey +program instead. + +.SH EXAMPLE +.sp 0 +wintermute$ opiegen otp-md5 495 wi01309 +.sp 0 +Secret Pass Phrase: +.sp 0 +GILL HUED GOES CHUM LIEU VAIN +.sp 0 +wintermute$ +.LP + +.SH BUGS +.BR opiegen(1) +can lull a user into revealing his/her password when remotely logged in, thus +defeating the purpose of OPIE. This is especially a problem with xterm. +.BR opiegen(1) implements simple checks to reduce the risk of a user making +this mistake. Better checks are needed. +.LP + +.SH SEE ALSO +.BR opiekey (1), +.BR opieserv (1), +.BR opie (4), +.BR opiepasswd (1), +.BR opieinfo (1), +.BR opiesu (1), +.BR opielogin (1), +.BR opieftpd (8), +.BR opiekeys (5), +.BR opieaccess (5) + +.SH AUTHOR +The opiegen(1) program was created by Craig Metz for OPIE 2.2. + +Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden +of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and +Craig Metz. + +S/Key is a trademark of Bell Communications Research (Bellcore). + +.SH CONTACT +OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join, +send an email request to: +.sp +skey-users-request@thumper.bellcore.com diff --git a/contrib/opie/opiegen.c b/contrib/opie/opiegen.c new file mode 100644 index 0000000..7f1ff34 --- /dev/null +++ b/contrib/opie/opiegen.c @@ -0,0 +1,88 @@ +/* opiegen.c: Sample OTP generator based on the opiegenerator() + library routine. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Modified by cmetz for OPIE 2.3. OPIE_PASS_MAX changed to + OPIE_SECRET_MAX. Send debug info to syslog. + Modified by cmetz for OPIE 2.2. Use FUNCTION definition et al. + Fixed include order. + Created at NRL for OPIE 2.2. +*/ +#include "opie_cfg.h" +#include +#if DEBUG +#include +#endif /* DEBUG */ +#include "opie.h" + +int main FUNCTION((argc, argv), int argc AND char *argv[]) +{ + char buffer[OPIE_CHALLENGE_MAX+1]; + char secret[OPIE_SECRET_MAX+1]; + char response[OPIE_RESPONSE_MAX+1]; + int result; + + if (opieinsecure()) { + fputs("Sorry, but you don't seem to be on a secure terminal.\n", stderr); +#if !DEBUG + exit(1); +#endif /* !DEBUG */ + } + + if (argc <= 1) { + fputs("Challenge: ", stderr); + if (!opiereadpass(buffer, sizeof(buffer)-1, 1)) + fprintf(stderr, "Error reading challenge!"); + } else { + char *ap, *ep, *c; + int i; + + ep = buffer + sizeof(buffer) - 1; + for (i = 1, ap = buffer; (i < argc) && (ap < ep); i++) { + c = argv[i]; + while ((*(ap++) = *(c++)) && (ap < ep)); + *(ap - 1) = ' '; + } + *(ap - 1) = 0; +#if DEBUG + syslog(LOG_DEBUG, "opiegen: challenge is +%s+\n", buffer); +#endif /* DEBUG */ + } + buffer[sizeof(buffer)-1] = 0; + + fputs("Secret pass phrase: ", stderr); + if (!opiereadpass(secret, OPIE_SECRET_MAX, 0)) { + fputs("Error reading secret pass phrase!\n", stderr); + exit(1); + }; + + switch (result = opiegenerator(buffer, secret, response)) { + case -2: + fputs("Not a valid OTP secret pass phrase.\n", stderr); + break; + case -1: + fputs("Error processing challenge!\n", stderr); + break; + case 1: + fputs("Not a valid OTP challenge.\n", stderr); + break; + case 0: + fputs(response, stdout); + fputc('\n', stdout); + fflush(stdout); + memset(secret, 0, sizeof(secret)); + exit(0); + default: + fprintf(stderr, "Unknown error %d!\n", result); + } + memset(secret, 0, sizeof(secret)); + return 1; +} diff --git a/contrib/opie/opieinfo.1 b/contrib/opie/opieinfo.1 new file mode 100644 index 0000000..c8d08f8 --- /dev/null +++ b/contrib/opie/opieinfo.1 @@ -0,0 +1,99 @@ +.\" opieinfo.1: Manual page for the opieinfo(1) program. +.\" +.\" %%% portions-copyright-cmetz +.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights +.\" Reserved. The Inner Net License Version 2 applies to these portions of +.\" the software. +.\" You should have received a copy of the license with this software. If +.\" you didn't get a copy, you may request one from . +.\" +.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan +.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned +.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +.\" License Agreement applies to this software. +.\" +.\" History: +.\" +.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation. +.\" Modified at NRL for OPIE 2.0. +.\" Written at Bellcore for the S/Key Version 1 software distribution +.\" (keyinfo.1). +.\" +.ll 6i +.pl 10.5i +.lt 6.0i +.TH OPIEINFO 1 "January 10, 1995" +.AT 3 +.SH NAME +opieinfo \- Extract sequence number and seed for future OPIE challenges. + +.SH SYNOPSIS +.B opieinfo +[\-v] [\-h] [ +.I user_name +] + +.SH DESCRIPTION +.I opieinfo +takes an optional user name and writes the current sequence number +and seed found in the OPIE key database for either the current user +or the user specified. opiekey is compatible with the +.IR keyinfo (1) +program +from Bellcore's S/Key Version 1 except that specification of a remote +system name is not permitted. +.sp +.I opieinfo +can be used to generate a listing of your future OPIE responses +if you are going to be without an OPIE calculator and still need to log into +the system. To do so, you would run something like: +.sp +.B opiekey \-n 42 `opieinfo` + +.SH OPTIONS +.TP +.B \-v +Display the version number and compile-time options, then exit. +.TP +.B \-h +Display a brief help message and exit. +.TP +.B +The name of a user whose key information you wish to display. The default is +the user running opieinfo. + +.SH EXAMPLE +.sp 0 +wintermute$ opieinfo +.sp 0 +495 wi01309 +.sp 0 +wintermute$ +.LP + +.SH FILES +.TP +/etc/opiekeys -- database of key information for the OPIE system. + +.SH SEE ALSO +.BR opie (4), +.BR opiekey (1), +.BR opiepasswd (1), +.BR opiesu (1), +.BR opielogin (1), +.BR opieftpd (8), +.BR opiekeys (5) +.BR opieaccess (5) + +.SH AUTHOR +Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden +of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and +Craig Metz. + +S/Key is a trademark of Bell Communications Research (Bellcore). + +.SH CONTACT +OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join, +send an email request to: +.sp +skey-users-request@thumper.bellcore.com diff --git a/contrib/opie/opieinfo.c b/contrib/opie/opieinfo.c new file mode 100644 index 0000000..f1b0acb --- /dev/null +++ b/contrib/opie/opieinfo.c @@ -0,0 +1,90 @@ +/* +opieinfo: Print a user's current OPIE sequence number and seed + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Removed unneeded debug message. + Modified by cmetz for OPIE 2.2. Use FUNCTION definition et al. + Fixed include order. Make everything static. Ifdef around + some headers. + Modified at NRL for OPIE 2.1. Substitute @@KEY_FILE@@. Re-write in + C. + Modified at NRL for OPIE 2.01. Remove hard-coded paths for grep and + awk and let PATH take care of it. Substitute for Makefile + variables $(EXISTS) and $(KEY_FILE). Only compute $WHO if + there's a key file. Got rid of grep since awk can do the job + itself. + Modified at NRL for OPIE 2.0. + Written at Bellcore for the S/Key Version 1 software distribution + (keyinfo) +*/ + +#include "opie_cfg.h" +#include +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#if HAVE_PWD_H +#include +#endif /* HAVE_PWD_H */ +#include "opie.h" + +/* extern char *optarg; */ +extern int errno, optind; + +static char *getusername FUNCTION_NOARGS +{ + struct passwd *p = getpwuid(getuid()); + + if (!p) + return getlogin(); + + return p->pw_name; +} + +int main FUNCTION((argc, argv), int argc AND char *argv[]) +{ + char *username; + struct opie opie; + int i; + + while ((i = getopt(argc, argv, "hv")) != EOF) { + switch (i) { + case 'v': + opieversion(); + case 'h': + default: + fprintf(stderr, "usage: %s [-h] [-v] [user_name]\n", argv[0]); + exit(0); + } + } + + if (optind < argc) + username = argv[optind]; + else + username = getusername(); + + if ((i = opielookup(&opie, username)) && (i != 2)) { + if (i < 0) + fprintf(stderr, "Error opening database! (errno = %d)\n", errno); + else + fprintf(stderr, "%s not found in database.\n", username); + exit(1); + } + + printf("%d %s\n", opie.opie_n - 1, opie.opie_seed); + + return 0; +} diff --git a/contrib/opie/opiekey.1 b/contrib/opie/opiekey.1 new file mode 100644 index 0000000..74fc8ca --- /dev/null +++ b/contrib/opie/opiekey.1 @@ -0,0 +1,173 @@ +.\" opiekey.1: Manual page for the opiekey(1) program. +.\" +.\" %%% portions-copyright-cmetz +.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights +.\" Reserved. The Inner Net License Version 2 applies to these portions of +.\" the software. +.\" You should have received a copy of the license with this software. If +.\" you didn't get a copy, you may request one from . +.\" +.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan +.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned +.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +.\" License Agreement applies to this software. +.\" +.\" History: +.\" +.\" Modified by cmetz for OPIE 2.3. Added -t documentation. Removed +.\" opie-bugs pointer. Removed opie-md5 and opie-md4 names. Fixed +.\" a bolding bug. Added -f flag. Added escapes on flags. Minor +.\" editorial changes. Updated example. +.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation. +.\" Re-worded retype documentation. Added opiegen reference. +.\" Added -x documentation. +.\" Modified at NRL for OPIE 2.0. +.\" Written at Bellcore for the S/Key Version 1 software distribution +.\" (key.1). +.\" +.ll 6i +.pl 10.5i +.lt 6.0i +.TH OPIEKEY 1 "February 20, 1996" +.AT 3 +.SH NAME +opiekey, otp-md4, otp-md5 \- Programs for computing responses to OTP challenges. + +.SH SYNOPSIS +.B opiekey +| +.B otp-md4 +| +.B otp-md5 +[\-v] [\-h] [\-f] [\-x] +.sp 0 +[\-t +.I +type +] [\-4|\-5] +[\-a] [\-n +.I count +] +.I sequence_number seed +.sp 0 + +.SH DESCRIPTION +.I opiekey +takes the optional count of the number of responses to +print along with a (maximum) sequence number and seed as command line +args. It prompts for the user's secret pass phrase and produces an OPIE +response as six words. If compiled to do so, it can prompt for the user's +secret pass phrase twice to help reduce errors due to mistypes. The second +password entry can be circumvented by entering only an end of line. +.I opiekey +is downward compatible with the +.IR key (1) +program from the Bellcore S/Key Version 1 distribution and several of its +variants. + +.SH OPTIONS +.TP +.B \-v +Display the version number and compile-time options, then exit. +.TP +.B \-h +Display a brief help message and exit. +.TP +.B \-4, \-5 +Selects MD4 or MD5, respectively, as the response generation algorithm. The +default for otp-md4 is MD4 and the default for opie-md5 is MD5. The default +for opiekey depends on compile-time configuration, but should be MD5. MD4 is +compatible with the Bellcore S/Key Version 1 distribution. +.TP +.B \-f +Force +.I opiekey +to continue, even where it normally shouldn't. This is currently used to +force opiekey to operate in even from terminals it believes to be insecure. +It can also allow users to disclose their secret pass phrases to attackers. +Use of the -f flag may be disabled by compile-time option in your particular +build of OPIE. +.TP +.B \-a +Allows you to input an arbitrary secret pass phrase, instead of running checks +against it. Arbitrary currently does not include '\0' or '\n' characters. This +can be used for backwards compatibility with key generators that do not check +passwords. +.TP +.B \-n +the number of one time access passwords to print. +The default is one. +.TP +.B \-x +Output the OTPs as hexadecimal numbers instead of six words. +.TP +.B \-t +Generate an extended response of the specified type. Supported types are: +.sp 1 +word six-word +.sp 0 +hex hexadecimal +.sp 0 +init hexadecimal re-initialization +.sp 0 +init-word six-word re-initialization +.sp 1 +The re-initialization responses +.I always +generate the simple active attack protection. +.TP +.SH EXAMPLE +.sp 0 +wintermute$ opiekey \-5 \-n 5 495 wi01309 +.sp 0 +Using MD5 algorithm to compute response. +.sp 0 +Reminder: Don't use opiekey from telnet or dial-in sessions. +.sp 0 +Enter secret pass phrase: +.sp 0 +491: HOST VET FOWL SEEK IOWA YAP +.sp 0 +492: JOB ARTS WERE FEAT TILE IBIS +.sp 0 +493: TRUE BRED JOEL USER HALT EBEN +.sp 0 +494: HOOD WED MOLT PAN FED RUBY +.sp 0 +495: SUB YAW BILE GLEE OWE NOR +.sp 0 +wintermute$ +.LP + +.SH BUGS +.BR opiekey(1) +can lull a user into revealing his/her password when remotely logged in, thus +defeating the purpose of OPIE. This is especially a problem with xterm. +.BR opiekey(1) +implements simple checks to reduce the risk of a user making +this mistake. Better checks are needed. +.LP + +.SH SEE ALSO +.BR opie (4), +.BR opiepasswd (1), +.BR opieinfo (1), +.BR opiesu (1), +.BR opielogin (1), +.BR opieftpd (8), +.BR opiekeys (5), +.BR opieaccess (5), +.BR opiegen (1) + +.SH AUTHOR +Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden +of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and +Craig Metz. + +S/Key is a trademark of Bell Communications Research (Bellcore). + +.SH CONTACT +OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join, +send an email request to: +.sp +skey-users-request@thumper.bellcore.com diff --git a/contrib/opie/opiekey.c b/contrib/opie/opiekey.c new file mode 100644 index 0000000..17b5ab0 --- /dev/null +++ b/contrib/opie/opiekey.c @@ -0,0 +1,375 @@ +/* opiekey.c: Stand-alone program for computing responses to OTP challenges. + + Takes a sequence number and seed (presumably from an OPIE challenge) + as command line arguments, prompts for the user's secret pass phrase, + and outputs a response. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. OPIE_PASS_MAX changed to + OPIE_SECRET_MAX. Added extended responses, which created + lots of changes. Eliminated extra variable. Added -x and + -t to help. Added -f flag. Added SHA support. + Modified by cmetz for OPIE 2.22. Print newline after seed too long + message. Check for minimum seed length. Correct a grammar + error. + Modified at NRL for OPIE 2.2. Check opiereadpass() return. + Change opiereadpass() calls to add echo arg. Use FUNCTION + definition et al. Check seed length here, too. Added back + hex output. Reworked final output function. + Modified at NRL for OPIE 2.0. + Written at Bellcore for the S/Key Version 1 software distribution + (skey.c). +*/ +#include "opie_cfg.h" + +#include +#include +#include + +#include "opie.h" + +#ifdef __MSDOS__ +#include +#endif + +#if HAVE_FCNTL_H +#include +#endif /* HAVE_FCNTL_H */ + +extern char *optarg; +extern int optind, opterr; + +int aflag = 0; + +char *algnames[] = { NULL, NULL, NULL, "SHA-1", "MD4", "MD5" }; +char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" }; + +/******** Begin real source code ***************/ + +static VOIDRET usage FUNCTION((s), char *s) +{ + fprintf(stderr, "usage: %s [-v] [-h] [-f] [-x] [-t type] [-4 | -5 | -s] [-a] [-n count] sequence_number seed\n", s); + exit(1); +} + +#define RESPONSE_STANDARD 0 +#define RESPONSE_WORD 1 +#define RESPONSE_HEX 2 +#define RESPONSE_INIT 3 +#define RESPONSE_INIT_WORD 4 +#define RESPONSE_UNKNOWN 5 + +struct _rtrans { + int type; + char *name; +}; + +static struct _rtrans rtrans[] = { + { RESPONSE_WORD, "word" }, + { RESPONSE_HEX, "hex" }, + { RESPONSE_INIT, "init" }, + { RESPONSE_INIT_WORD, "init-word" }, + { RESPONSE_STANDARD, "" }, + { RESPONSE_STANDARD, "standard" }, + { RESPONSE_STANDARD, "otp" }, + { RESPONSE_UNKNOWN, NULL } +}; + +static void getsecret FUNCTION((secret, promptextra, retype), char *secret AND char *promptextra AND int flags) +{ + fprintf(stderr, "Enter %ssecret pass phrase: ", promptextra); + if (!opiereadpass(secret, OPIE_SECRET_MAX, 0)) { + fprintf(stderr, "Error reading %ssecret pass phrase!\n", promptextra); + exit(1); + } + if (secret[0] && (flags & 1)) { + char verify[OPIE_SECRET_MAX + 1]; + + fprintf(stderr, "Again %ssecret pass phrase: ", promptextra); + if (!opiereadpass(verify, OPIE_SECRET_MAX, 0)) { + fprintf(stderr, "Error reading %ssecret pass phrase!\n", promptextra); + memset(verify, 0, sizeof(verify)); + memset(secret, 0, sizeof(secret)); + exit(1); + } + if (verify[0] && strcmp(verify, secret)) { + fprintf(stderr, "They don't match. Try again.\n"); + memset(verify, 0, sizeof(verify)); + memset(secret, 0, sizeof(secret)); + exit(1); + } + memset(verify, 0, sizeof(verify)); + } + if (!(flags & 2) && opiepasscheck(secret)) { + memset(secret, 0, sizeof(secret)); + fprintf(stderr, "Secret pass phrases must be between %d and %d characters long.\n", OPIE_SECRET_MIN, OPIE_SECRET_MAX); + exit(1); + }; +} + +int main FUNCTION((argc, argv), int argc AND char *argv[]) +{ + /* variable declarations */ + unsigned algorithm = MDX; /* default algorithm per Makefile's MDX + symbol */ + int keynum = 0; + int i; + int count = 1; + char secret[OPIE_SECRET_MAX + 1], newsecret[OPIE_SECRET_MAX + 1]; + char key[8], newkey[8]; + char cko[8], ckn[8], ckxor[8], cv[8]; + char *seed, newseed[OPIE_SEED_MAX + 1]; + char response[OPIE_RESPONSE_MAX + 1]; + char *slash; + int hex = 0; + int type = RESPONSE_STANDARD; + int force; + + if (slash = strchr(argv[0], '/')) + slash++; + else + slash = argv[0]; + + if (!strcmp(slash, "key") || strstr(slash, "md4")) + algorithm = 4; + + if (strstr(slash, "md5")) + algorithm = 5; + + if (strstr(slash, "sha")) + algorithm = 3; + + while ((i = getopt(argc, argv, "fhvn:x45at:s")) != EOF) { + switch (i) { + case 'v': + opieversion(); + + case 'n': + count = atoi(optarg); + break; + + case 'x': + hex = 1; + break; + + case 'f': +#if INSECURE_OVERRIDE + force = 1; +#else /* INSECURE_OVERRIDE */ + fprintf(stderr, "Sorry, but the -f option is not supported by this build of OPIE.\n"); +#endif /* INSECURE_OVERRIDE */ + break; + + case '4': + /* use MD4 algorithm */ + algorithm = 4; + break; + + case '5': + /* use MD5 algorithm */ + algorithm = 5; + break; + + case 'a': + aflag = 1; + break; + + case 't': + { + struct _rtrans *r; + for (r = rtrans; r->name && strcmp(r->name, optarg); r++); + if (!r->name) { + fprintf(stderr, "%s: %s: unknown response type.\n", argv[0], optarg); + exit(1); + } + type = r->type; + } + break; + + case 's': + algorithm = 3; + break; + + default: + usage(argv[0]); + } + } + + if ((argc - optind) < 2) + usage(argv[0]); + + fprintf(stderr, "Using the %s algorithm to compute response.\n", algnames[algorithm]); + + /* get sequence number, which is next-to-last parameter */ + keynum = atoi(argv[optind]); + if (keynum < 1) { + fprintf(stderr, "Sequence number %s is not positive.\n", argv[optind]); + exit(1); + } + /* get seed string, which is last parameter */ + seed = argv[optind + 1]; + { + i = strlen(seed); + + if (i > OPIE_SEED_MAX) { + fprintf(stderr, "Seeds must be less than %d characters long.\n", OPIE_SEED_MAX); + exit(1); + } + if (i < OPIE_SEED_MIN) { + fprintf(stderr, "Seeds must be greater than %d characters long.\n", OPIE_SEED_MIN); + exit(1); + } + } + + fprintf(stderr, "Reminder: Don't use opiekey from telnet or dial-in sessions.\n"); + + if (opieinsecure()) { + fprintf(stderr, "Sorry, but you don't seem to be on the console or a secure terminal.\n"); +#if INSECURE_OVERRIDE + if (force) + fprintf(stderr, "Warning: Continuing could disclose your secret pass phrase to an attacker!\n"); + else +#endif /* INSECURE_OVERRIDE */ + exit(1); + } + + if ((type == RESPONSE_INIT) || (type == RESPONSE_INIT_WORD)) { +#if RETYPE + getsecret(secret, "old ", 1); +#else /* RETYPE */ + getsecret(secret, "old ", 0); +#endif /* RETYPE */ + getsecret(newsecret, "new ", 1); + if (!newsecret[0]) + strcpy(newsecret, secret); + + if (opienewseed(strcpy(newseed, seed)) < 0) { + fprintf(stderr, "Error updating seed.\n"); + goto error; + } + + if (opiekeycrunch(algorithm, newkey, newseed, newsecret)) { + fprintf(stderr, "%s: key crunch failed (1)\n", argv[0]); + goto error; + } + + for (i = 0; i < 499; i++) + opiehash(newkey, algorithm); + + if (opiekeycrunch(algorithm | 0x10, cko, seed, secret)) { + fprintf(stderr, "%s: key crunch failed (2)\n", argv[0]); + goto error; + } + + if (opiekeycrunch(algorithm | 0x10, ckn, newseed, newsecret)) { + fprintf(stderr, "%s: key crunch failed (3)\n", argv[0]); + goto error; + } + + for (i = 0; i < 8; i++) + ckxor[i] = cko[i] ^ ckn[i]; + } else +#if RETYPE + getsecret(secret, "", 1); +#else /* RETYPE */ + getsecret(secret, "", 0); +#endif /* RETYPE */ + + /* Crunch seed and secret password into starting key normally */ + if (opiekeycrunch(algorithm, key, seed, secret)) { + fprintf(stderr, "%s: key crunch failed\n", argv[0]); + goto error; + } + + for (i = 0; i <= (keynum - count); i++) + opiehash(key, algorithm); + + { + char buf[OPIE_SEED_MAX + 48 + 1]; + char *c; + + for (; i <= keynum; i++) { + if (count > 1) + printf("%d: %s", i, (type == RESPONSE_STANDARD) ? "" : "\n"); + + switch(type) { + case RESPONSE_STANDARD: + if (hex) + opiebtoh(response, key); + else + opiebtoe(response, key); + break; + case RESPONSE_WORD: + strcpy(response, "word:"); + strcat(response, opiebtoe(buf, key)); + break; + case RESPONSE_HEX: + strcpy(response, "hex:"); + strcat(response, opiebtoh(buf, key)); + break; + case RESPONSE_INIT: + case RESPONSE_INIT_WORD: + if (type == RESPONSE_INIT) { + strcpy(response, "init:"); + strcat(response, opiebtoh(buf, key)); + sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed); + strcat(response, buf); + strcat(response, opiebtoh(buf, newkey)); + strcat(response, ":"); + strcat(response, opiebtoh(buf, ckxor)); + strcat(response, ":"); + } else { + strcpy(response, "init-word:"); + strcat(response, opiebtoe(buf, key)); + sprintf(buf, ":%s 499 %s:", algids[algorithm], newseed); + strcat(response, buf); + strcat(response, opiebtoe(buf, newkey)); + strcat(response, ":"); + strcat(response, opiebtoe(buf, ckxor)); + strcat(response, ":"); + } + + c = buf; + memcpy(c, cko, sizeof(cko)); c += sizeof(cko); + memcpy(c, key, sizeof(key)); c += sizeof(key); +#ifdef HAVE_ANSISPRINTF + c += sprintf(c, "%s 499 %s", algids[algorithm], newseed); +#else /* HAVE_ANSISPRINTF */ + sprintf(c, "%s 499 %s", algids[algorithm], newseed); + while(*c) c++; +#endif /* HAVE_ANSISPRINTF */ + memcpy(c, newkey, sizeof(newkey)); c += sizeof(newkey); + memcpy(c, ckxor, sizeof(ckxor)); c += sizeof(ckxor); + memcpy(c, cko, sizeof(cko)); c += sizeof(cko); + opiehashlen(algorithm, buf, cv, (unsigned int)c - (unsigned int)buf); + + strcat(response, (type == RESPONSE_INIT) ? opiebtoh(buf, cv) : opiebtoe(buf, cv)); + break; + } + puts(response); + opiehash(key, algorithm); + } + } + + memset(secret, 0, sizeof(secret)); + memset(newsecret, 0, sizeof(newsecret)); + return 0; + +error: + memset(secret, 0, sizeof(secret)); + memset(newsecret, 0, sizeof(newsecret)); + return 1; +} diff --git a/contrib/opie/opiekeys.5 b/contrib/opie/opiekeys.5 new file mode 100644 index 0000000..c4ef5f4 --- /dev/null +++ b/contrib/opie/opiekeys.5 @@ -0,0 +1,66 @@ +.\" opieaccess.5: Manual page describing the /etc/opiekeys file. +.\" +.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan +.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned +.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +.\" License Agreement applies to this software. +.\" +.\" History: +.\" +.\" Written at NRL for OPIE 2.0. +.\" +.ll 6i +.pl 10.5i +.\" @(#)opiekeys.1 2.0 (NRL) 1/10/95 +.\" +.lt 6.0i +.TH OPIEKEYS 1 "January 10, 1995" +.AT 3 +.SH NAME +[/etc/]opiekeys \- OPIE database of user key information + +.SH DESCRIPTION +The +.I opiekeys +file contains user information used by the OPIE software to authenticate +users. The +.I opiekeys +file is backwards compatible with the S/Key +.I /etc/skeykeys +database file, but only if the hashing algorithm (MD4 and MD5) is the same +between S/Key and OPIE (i.e., MD5 OPIE cannot use MD4 S/Key keys). The +.I opiekeys +file consists of six fields separated by spaces (tabs are properly +interpreted, but spaces should be used instead) as follows: +.PP +.nf +.ta \w' 'u +Field Description +name User's login name. +sequence User's sequence number. +seed User's seed. +key User's last response (hex). +date Last change date. +time Last change time. +.fi +.SH SEE ALSO +.BR opie (4), +.BR opiekeys (5), +.BR opiepasswd (1), +.BR opieinfo (1), +.BR opiesu (1), +.BR opielogin (1), +.BR opieftpd (8) + +.SH AUTHOR +Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden +of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and +Craig Metz. + +S/Key is a trademark of Bell Communications Research (Bellcore). + +.SH CONTACT +OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join, +send an email request to: +.sp +skey-users-request@thumper.bellcore.com diff --git a/contrib/opie/opielogin.1 b/contrib/opie/opielogin.1 new file mode 100644 index 0000000..0f687cc --- /dev/null +++ b/contrib/opie/opielogin.1 @@ -0,0 +1,131 @@ +.\" opielogin.1: Manual page for the opielogin(1) program. +.\" +.\" %%% portions-copyright-cmetz +.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights +.\" Reserved. The Inner Net License Version 2 applies to these portions of +.\" the software. +.\" You should have received a copy of the license with this software. If +.\" you didn't get a copy, you may request one from . +.\" +.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan +.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned +.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +.\" License Agreement applies to this software. +.\" +.\" History: +.\" +.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation. +.\" Modified at NRL for OPIE 2.0. +.\" Option descriptions added from BSD. +.\" Written at Bellcore for the S/Key Version 1 software distribution +.\" (keylogin.1). +.\" +.ll 6i +.pl 10.5i +.lt 6.0i +.TH OPIELOGIN 1 "January 10, 1995" +.AT 3 + +.SH NAME +opielogin \- Replacement for login(1) that issues OPIE challenges. + +.SH SYNOPSIS +.B opielogin +[ -p ] [ -r +.I hostname +| -h +.I hostname +| -f +.I username +.sp 0 +| +.I username +] + +.SH DESCRIPTION +.I opielogin +provides a replacement for the +.IR login (1) +program that provides OPIE challenges +to users and accepts OPIE responses. It is downward compatible with the +.IR keylogin(1) +program from the Bellcore S/Key Version 1 distribution, which, in +turn, is downward compatible with the +.IR login(1) +program from the 4.3BSD Net/2 distribution. + +.SH OPTIONS +.TP +.B \-p +By default, login discards any previous environment. The \-p +option disables this behavior. +.TP +.B \-r +Process remote login from +.I hostname. +.TP +.B \-h +The -h option specifies the host from which the connection was +received. It is used by various daemons such as telnetd(8). +This option may only be used by the super\-user. +.TP +.B \-f +The -f option is used when a user name is specified to indicate +that proper authentication has already been done and that no +password need be requested. This option may only be used by the +super\-user or when an already logged in user is logging in as +themselves. +.TP +.I username +The user name to log in as. +.SH EXAMPLE +.sp 0 +wintermute$ opielogin +.sp 0 +login: kebe +.sp 0 +otp-md5 499 wi43143 +.sp 0 +Password: (echo on) +.sp 0 +Password:SLY BLOB TOUR POP BRED EDDY +.sp 0 + +.sp 0 + Welcome to wintermute. +.sp 0 + +.sp 0 +wintermute$ +.LP +.SH FILES +.TP +/etc/opiekeys -- database of information for the OPIE system. +.TP +/etc/opieaccess -- list of safe and unsafe networks and masks to go with them. +.TP +$HOME/.opiealways -- presence makes OPIE for logins mandatory for the user. + +.SH SEE ALSO +.BR login (1), +.BR opie (4), +.BR opiekey (1), +.BR opiepasswd (1), +.BR opieinfo (1), +.BR opiesu (1), +.BR opieftpd (8), +.BR opiekeys (5), +.BR opieaccess (5) + +.SH AUTHOR +Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden +of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and +Craig Metz. + +S/Key is a trademark of Bell Communications Research (Bellcore). + +.SH CONTACT +OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join, +send an email request to: +.sp +skey-users-request@thumper.bellcore.com diff --git a/contrib/opie/opielogin.c b/contrib/opie/opielogin.c new file mode 100644 index 0000000..8189293 --- /dev/null +++ b/contrib/opie/opielogin.c @@ -0,0 +1,1428 @@ +/* opielogin.c: The infamous /bin/login + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Process login environment files. + Made logindevperm/fbtab handling more generic. Kluge around + Solaris drain bamage differently (maybe better?). Maybe + allow cleartext logins even when opiechallenge() fails. + Changed the conditions on when time.h and sys/time.h are + included. Send debug info to syslog. Use opielogin() instead + of dealing with utmp/setlogin() here. + Modified by cmetz for OPIE 2.22. Call setlogin(). Decreased default + timeout to two minutes. Use opiereadpass() flags to get + around Solaris drain bamage. + Modified by cmetz for OPIE 2.21. Took the sizeof() the wrong thing. + Modified by cmetz for OPIE 2.2. Changed prompts to ask for OTP + response where appropriate. Simple though small speed-up. + Don't allow cleartext if echo on. Don't try to clear + non-blocking I/O. Use opiereadpass(). Don't mess with + termios (as much, at least) -- that's opiereadpass()'s + job. Change opiereadpass() calls to add echo arg. Fixed + CONTROL macro. Don't modify argv (at least, unless + we have a reason to). Allow user in if ruserok() says + so. Removed useless strings (I don't think that + removing the ucb copyright one is a problem -- please + let me know if I'm wrong). Use FUNCTION declaration et + al. Moved definition of TRUE here. Ifdef around more + headers. Make everything static. Removed support for + omitting domain name if same domain -- it generally + didn't work and it would be a big portability problem. + Use opiereadpass() in getloginname() and then post- + process. Added code to grab hpux time zone from + /etc/src.sh. Renamed MAIL_DIR to PATH_MAIL. Removed + dupe catchexit and extraneous closelog. openlog() as + soon as possible because SunOS syslog is broken. + Don't print an extra blank line before a new Response + prompt. + Modified at NRL for OPIE 2.2. Changed strip_crlf to stripcrlf. + Do opiebackspace() on entries. + Modified at NRL for OPIE 2.1. Since we don't seem to use the + result of opiechallenge() anymore, discard it. Changed + BSD4_3 to HAVE_GETTTYNAM. Other symbol changes for + autoconf. Removed obselete usage comment. Removed + des_crypt.h. File renamed to opielogin.c. Added bletch + for setpriority. Added slash between MAIL_DIR and name. + Modified at NRL for OPIE 2.02. Flush stdio after printing login + prompt. Fixed Solaris shadow password problem introduced + in OPIE 2.01 (the shadow password structure is spwd, not + spasswd). + Modified at NRL for OPIE 2.01. Changed password lookup handling + to use a static structure to avoid problems with drain- + bamaged shadow password packages. Make sure to close + syslog by function to avoid problems with drain bamaged + syslog implementations. Log a few interesting errors. + Modified at NRL for OPIE 2.0. + Modified at Bellcore for the Bellcore S/Key Version 1 software + distribution. + Originally from BSD. +*/ +/* + * Portions of this software are + * Copyright (c) 1980,1987 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#include "opie_cfg.h" /* OPIE: defines symbols for filenames & pathnames */ +#if HAVE_SYS_PARAM_H +#include +#endif /* HAVE_SYS_PARAM_H */ +#include +#include + +#if HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H +#include +#endif /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */ + +#if TIME_WITH_SYS_TIME +# include +# include +#else /* TIME_WITH_SYS_TIME */ +#if HAVE_SYS_TIME_H +#include +#else /* HAVE_SYS_TIME_H */ +#include +#endif /* HAVE_SYS_TIME_H */ +#endif /* TIME_WITH_SYS_TIME */ + +#if HAVE_SYS_FILE_H +#include +#endif /* HAVE_SYS_FILE_H */ +#include +#if HAVE_PWD_H +#include /* POSIX Password routines */ +#endif /* HAVE_PWD_H */ +#include +#include +#if HAVE_UNISTD_H +#include /* Basic POSIX macros and functions */ +#endif /* HAVE_UNISTD_H */ +#include /* POSIX terminal I/O */ +#if HAVE_STRING_H +#include /* ANSI C string functions */ +#endif /* HAVE_STRING_H */ +#include /* File I/O functions */ +#include +#include +#include +#include /* contains types needed for next include file */ +#include /* Inet addr<-->ascii functions */ +#if HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ + +#ifdef QUOTA +#include +#endif + +#if HAVE_GETTTYNAM +#include /* non-portable routines used only a few places */ +#include +#endif /* HAVE_GETTTYNAM */ + +#include "opie.h" + +#define TTYGID(gid) tty_gid(gid) /* gid that owns all ttys */ + +#define NMAX 32 +#define HMAX 256 + +#if HAVE_LASTLOG_H +#include +#endif /* HAVE_LASTLOG_H */ + +static int rflag = 0; +static int usererr = -1; +static int stopmotd; +static char rusername[NMAX + 1]; +static char name[NMAX + 1] = ""; +static char minusnam[16] = "-"; +static char *envinit[1]; /* now set by setenv calls */ +static char term[64] = "\0"; /* important to initialise to a NULL string */ +static char host[HMAX + 1] = "\0"; +static struct passwd nouser; +static struct passwd thisuser; + +#if HAVE_SHADOW_H +#include +#endif /* HAVE_SHADOW_H */ + +static char *ttyprompt; + +#ifdef PERMSFILE +extern char *home; +#endif /* PERMSFILE */ + +static struct termios attr; + +extern int errno; + +static int ouroptind; +static char *ouroptarg; + +#if HAVE_LASTLOG_H +#ifndef _PATH_LASTLOG +#define _PATH_LASTLOG "/var/adm/lastlog" +#endif /* _PATH_LASTLOG */ + +static char lastlog[] = _PATH_LASTLOG; +#endif /* HAVE_LASTLOG_H */ + +/* + * The "timeout" variable bounds the time given to login. + * We initialize it here for safety and so that it can be + * patched on machines where the default value is not appropriate. + */ +static int timeout = 120; + +static void getstr __P((char *, int, char *)); + +#if HAVE_CRYPT_H +#include +#endif /* HAVE_CRYPT_H */ + +#undef TRUE +#define TRUE -1 + +#ifdef TIOCSWINSZ +/* Windowing variable relating to JWINSIZE/TIOCSWINSZ/TIOCGWINSZ. This is +available on BSDish systems and at least Solaris 2.x, but portability to +other systems is questionable. Use within this source code module is +protected by suitable defines. + +I'd be interested in hearing about a more portable approach. rja */ + +static struct winsize win = {0, 0, 0, 0}; +#endif + + +/*------------------ BEGIN REAL CODE --------------------------------*/ + +/* We allow the malloc()s to potentially leak data out because we can +only call this routine about four times in the lifetime of this process +and the kernel will free all heap memory when we exit or exec. */ +static int lookupuser FUNCTION_NOARGS +{ + struct passwd *pwd; +#if HAVE_SHADOW + struct spwd *spwd; +#endif /* HAVE_SHADOW */ + + memcpy(&thisuser, &nouser, sizeof(thisuser)); + + if (!(pwd = getpwnam(name))) + return -1; + + thisuser.pw_uid = pwd->pw_uid; + thisuser.pw_gid = pwd->pw_gid; + + if (!(thisuser.pw_name = malloc(strlen(pwd->pw_name) + 1))) + goto lookupuserbad; + strcpy(thisuser.pw_name, pwd->pw_name); + + if (!(thisuser.pw_dir = malloc(strlen(pwd->pw_dir) + 1))) + goto lookupuserbad; + strcpy(thisuser.pw_dir, pwd->pw_dir); + + if (!(thisuser.pw_shell = malloc(strlen(pwd->pw_shell) + 1))) + goto lookupuserbad; + strcpy(thisuser.pw_shell, pwd->pw_shell); + +#if HAVE_SHADOW + if (!(spwd = getspnam(name))) + goto lookupuserbad; + + pwd->pw_passwd = spwd->sp_pwdp; + + endspent(); +#endif /* HAVE_SHADOW */ + + if (!(thisuser.pw_passwd = malloc(strlen(pwd->pw_passwd) + 1))) + goto lookupuserbad; + strcpy(thisuser.pw_passwd, pwd->pw_passwd); + + endpwent(); + + return ((thisuser.pw_passwd[0] == '*') || (thisuser.pw_passwd[0] == '#')); + +lookupuserbad: + memcpy(&thisuser, &nouser, sizeof(thisuser)); + return -1; +} + +static VOIDRET getloginname FUNCTION_NOARGS +{ + register char *namep; + char c, d; + int flags; + static int first = 1; + + memset(name, 0, sizeof(name)); + + d = 0; + while (name[0] == '\0') { + flags = 1; + if (ttyprompt) { + if (first) { + flags = 4; + first--; + } else + printf(ttyprompt); + } else + printf("login: "); + fflush(stdout); + if (++d == 3) + exit(0); + if (!opiereadpass(name, sizeof(name)-1, flags)) { + syslog(LOG_CRIT, "End-of-file (or other error?) on stdin!"); + exit(0); + } + for (namep = name; *namep; namep++) { + if (c == ' ') + c = '_'; + } + } +} + +static VOIDRET timedout FUNCTION((i), int i) +{ + /* input variable declared just to keep the compiler quiet */ + printf("Login timed out after %d seconds\n", timeout); + syslog(LOG_CRIT, "Login timed out after %d seconds!", timeout); + exit(0); +} + +#if !HAVE_MOTD_IN_PROFILE +static VOIDRET catch FUNCTION((i), int i) +{ + /* the input variable is declared to keep the compiler quiet */ + signal(SIGINT, SIG_IGN); + stopmotd++; +} +#endif /* !HAVE_MOTD_IN_PROFILE */ + +static VOIDRET catchexit FUNCTION_NOARGS +{ + int i; + tcsetattr(STDIN_FILENO, TCSANOW, &attr); + putchar('\n'); + closelog(); + for (i = sysconf(_SC_OPEN_MAX); i > 2; i--) + close(i); +} + +static int rootterm FUNCTION((ttyn), char *ttyn) +{ +#if HAVE_GETTTYNAM +/* The getttynam() call and the ttyent structure first appeared in 4.3 BSD and +are not portable to System V systems such as Solaris 2.x. or modern versions +of IRIX rja */ + register struct ttyent *t; + char *tty; + + tty = strrchr(ttyn, '/'); + + if (tty == NULL) + tty = ttyn; + else + tty++; + + if ((t = getttynam(tty)) != NULL) + return (t->ty_status & TTY_SECURE); + + return (1); /* when in doubt, allow root logins */ + +#elif HAVE_ETC_DEFAULT_LOGIN + + FILE *filno; + char line[128]; + char *next, *next2; + +/* SVR4 only permits two security modes for root logins: 1) only from CONSOLE, +if the string "CONSOLE=/dev/console" exists and is not commented out with "#" +characters, or 2) from anywhere. + +So we open /etc/default/login file grab the file contents one line at a time +verify that the line being tested isn't commented out check for the substring +"CONSOLE" and decide whether to permit this attempted root login/su. */ + + if ((filno = fopen("/etc/default/login", "r")) != NULL) { + while (fgets(line, 128, filno) != NULL) { + next = line; + + if ((line[0] != '#') && (next = strstr(line, "CONSOLE"))) { + next += 7; /* get past the string "CONSOLE" */ + + while (*next && (*next == ' ') || (*next == '\t')) + next++; + + if (*(next++) != '=') + break; /* some weird character, get next line */ + + next2 = next; + while (*next2 && (*next2 != '\t') && (*next2 != ' ') && + (*next2 != '\n')) + next2++; + *next2 = 0; + + return !strcmp(ttyn, next); /* Allow the login if and only if the + user's terminal line matches the + setting for CONSOLE */ + } + } /* end while another line could be obtained */ + } /* end if could open file */ + return (1); /* when no CONSOLE line exists, root can login from anywhere */ +#elif HAVE_SECURETTY + { + FILE *f; + char buffer[1024], *c; + int rc = 0; + + if (!(f = fopen("/etc/securetty", "r"))) + return 1; + + if (c = strstr(ttyn, "/dev/")) + ttyn += 5; + + if (c = strrchr(ttyn, '/')) + ttyn = ++c; + + while (fgets(buffer, sizeof(buffer), f)) { + if (c = strrchr(buffer, '\n')) + *c = 0; + + if (!(c = strrchr(buffer, '/'))) + c = buffer; + else + c++; + + if (!strcmp(c, ttyn)) + rc = 1; + }; + + fclose(f); + return rc; + } +#else + return (1); /* when in doubt, allow root logins */ +#endif +} + +static int doremotelogin FUNCTION((host), char *host) +{ + int rc; + + getstr(rusername, sizeof(rusername), "remuser"); + getstr(name, sizeof(name), "locuser"); + getstr(term, sizeof(term), "Terminal type"); + if (getuid()) { + memcpy(&thisuser, &nouser, sizeof(thisuser)); + syslog(LOG_ERR, "getuid() failed"); + return (-1); + } + if (lookupuser()) { + syslog(LOG_ERR, "lookup failed for user %s", name); + return (-1); + } + rc = ruserok(host, !thisuser.pw_uid, rusername, name); + if (rc == -1) { + syslog(LOG_ERR, + "ruserok failed, host=%s, uid=%d, remote username=%s, local username=%s", + host, thisuser.pw_uid, rusername, name); + } + return rc; +} + + +static VOIDRET getstr FUNCTION((buf, cnt, err), char *buf AND int cnt AND char *err) +{ + char c; + + do { + if (read(0, &c, 1) != 1) + exit(1); + if (--cnt < 0) { + printf("%s too long\r\n", err); + syslog(LOG_CRIT, "%s too long", err); + exit(1); + } + *buf++ = c; + } + while ((c != 0) && (c != '~')); +} + +struct speed_xlat { + char *c; + int i; +} speeds[] = { + +#ifdef B0 + { + "0", B0 + }, +#endif /* B0 */ +#ifdef B50 + { + "50", B50 + }, +#endif /* B50 */ +#ifdef B75 + { + "75", B75 + }, +#endif /* B75 */ +#ifdef B110 + { + "110", B110 + }, +#endif /* B110 */ +#ifdef B134 + { + "134", B134 + }, +#endif /* B134 */ +#ifdef B150 + { + "150", B150 + }, +#endif /* B150 */ +#ifdef B200 + { + "200", B200 + }, +#endif /* B200 */ +#ifdef B300 + { + "300", B300 + }, +#endif /* B300 */ +#ifdef B600 + { + "600", B600 + }, +#endif /* B600 */ +#ifdef B1200 + { + "1200", B1200 + }, +#endif /* B1200 */ +#ifdef B1800 + { + "1800", B1800 + }, +#endif /* B1800 */ +#ifdef B2400 + { + "2400", B2400 + }, +#endif /* B2400 */ +#ifdef B4800 + { + "4800", B4800 + }, +#endif /* B4800 */ +#ifdef B7200 + { + "7200", B7200 + }, +#endif /* B7200 */ +#ifdef B9600 + { + "9600", B9600 + }, +#endif /* B9600 */ +#ifdef B14400 + { + "14400", B14400 + }, +#endif /* B14400 */ +#ifdef B19200 + { + "19200", B19200 + }, +#endif /* B19200 */ +#ifdef B28800 + { + "28800", B28800 + }, +#endif /* B28800 */ +#ifdef B38400 + { + "38400", B38400 + }, +#endif /* B38400 */ +#ifdef B57600 + { + "57600", B57600 + }, +#endif /* B57600 */ +#ifdef B115200 + { + "115200", B115200 + }, +#endif /* B115200 */ +#ifdef B230400 + { + "230400", B230400 + }, +#endif /* 230400 */ + { + NULL, 0 + } +}; + +static VOIDRET doremoteterm FUNCTION((term), char *term) +{ + register char *cp = strchr(term, '/'); + char *speed; + struct speed_xlat *x; + + if (cp) { + *cp++ = '\0'; + speed = cp; + cp = strchr(speed, '/'); + if (cp) + *cp++ = '\0'; + for (x = speeds; x->c != NULL; x++) + if (strcmp(x->c, speed) == 0) { + cfsetispeed(&attr, x->i); + cfsetospeed(&attr, x->i); + break; + } + } +} + +static int tty_gid FUNCTION((default_gid), int default_gid) +{ + struct group *gr; + int gid = default_gid; + + gr = getgrnam(TTYGRPNAME); + if (gr != (struct group *) 0) + gid = gr->gr_gid; + endgrent(); + return (gid); +} + +int main FUNCTION((argc, argv), int argc AND char *argv[]) +{ + extern char **environ; + register char *namep; + struct opie opie; + + int invalid, quietlog; + FILE *nlfd; + char *tty, host[256]; + int pflag = 0, hflag = 0, fflag = 0; + int t, c; + int i; + char *p; + char opieprompt[OPIE_CHALLENGE_MAX + 1]; + int pwok, otpok, af_pwok; + char *pp; + char buf[256]; + int uid; + int opiepassed; + +#ifndef DEBUG + if (geteuid()) { + fprintf(stderr, "This program requires super-user priveleges.\n"); + exit(1); + } +#endif /* DEBUG */ + + openlog("login", LOG_ODELAY, LOG_AUTH); + + { + struct termios termios; + fd_set fds; + struct timeval timeval; + + memset(&timeval, 0, sizeof(struct timeval)); + + FD_ZERO(&fds); + FD_SET(0, &fds); + + if (select(1, &fds, NULL, NULL, &timeval)) { +#ifdef DEBUG + syslog(LOG_DEBUG, "reading user name from tty buffer"); +#endif /* DEBUG */ + + if (tcgetattr(0, &termios)) { +#ifdef DEBUG + syslog(LOG_DEBUG, "tcgetattr(0, &termios) failed"); +#endif /* DEBUG */ + exit(1); + } + + termios.c_lflag &= ~ECHO; + + if (tcsetattr(0, TCSANOW, &termios)) { +#ifdef DEBUG + syslog(LOG_DEBUG, "tcsetattr(0, &termios) failed"); +#endif /* DEBUG */ + exit(1); + } + + if ((i = read(0, name, sizeof(name)-1)) > 0) + name[i] = 0; + } + } + + /* initialisation */ + host[0] = '\0'; + opieprompt[0] = '\0'; + + if (p = getenv("TERM")) { +#ifdef DEBUG + syslog(LOG_DEBUG, "environment TERM=%s", p); +#endif /* DEBUG */ + strncpy(term, p, sizeof(term)); + }; + + memset(&nouser, 0, sizeof(nouser)); + nouser.pw_uid = -1; + nouser.pw_gid = -1; + nouser.pw_passwd = "#nope"; + nouser.pw_name = nouser.pw_gecos = nouser.pw_dir = nouser.pw_shell = ""; + +#if HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H + setpriority(PRIO_PROCESS, 0, 0); +#endif /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */ + + signal(SIGALRM, timedout); + alarm(timeout); + signal(SIGQUIT, SIG_IGN); + signal(SIGINT, SIG_IGN); + +#if DOTTYPROMPT + ttyprompt = (char *) getenv("TTYPROMPT"); +#endif /* TTYPROMPT */ + +#ifdef QUOTA + quota(Q_SETUID, 0, 0, 0); +#endif + +#ifdef DEBUG + { + int foo; + + syslog(LOG_DEBUG, "my args are: (argc=%d)", foo = argc); + while (--foo) + syslog(LOG_DEBUG, "%d: %s", foo, argv[foo]); + } +#endif /* DEBUG */ + +/* Some OSs pass environment variables on the command line. All of them except + for TERM get eaten. */ + + i = argc; + while (--i) + if (strchr(argv[i], '=')) { +#ifdef DEBUG + syslog(LOG_DEBUG, "eating %s", argv[i]); +#endif /* DEBUG */ + argc--; + if (!strncmp(argv[i], "TERM=", 5)) { + strncpy(term, &(argv[i][5]), sizeof(term)); + term[sizeof(term) - 1] = 0; +#ifdef DEBUG + syslog(LOG_DEBUG, "passed TERM=%s, ouroptind = %d", term, i); +#endif /* DEBUG */ + } + } +/* Implement our own getopt()-like functionality, but do so in a much more + strict manner to prevent security problems. */ + for (ouroptind = 1; ouroptind < argc; ouroptind++) { + i = 0; + if (argv[ouroptind]) + if (argv[ouroptind][0] == '-') + if (i = argv[ouroptind][1]) + if (!argv[ouroptind][2]) + switch (i) { + case 'd': + if (++ouroptind == argc) + exit(1); +/* The '-d' option is apparently a performance hack to get around + ttyname() being slow. The potential does exist for it to be used + for malice, and it does not seem to be strictly necessary, so we + will just eat it. */ + break; + + case 'r': + if (rflag || hflag || fflag) { + printf("Other options not allowed with -r\n"); + exit(1); + } + if (++ouroptind == argc) + exit(1); + + ouroptarg = argv[ouroptind]; + + if (!ouroptarg) + exit(1); + + rflag = -1; + if (!doremotelogin(ouroptarg)) + rflag = 1; + + strncpy(host, ouroptarg, sizeof(host)); + break; + + case 'h': + if (!getuid()) { + if (rflag || hflag || fflag) { + printf("Other options not allowed with -h\n"); + exit(1); + } + hflag = 1; + + if (++ouroptind == argc) + exit(1); + + ouroptarg = argv[ouroptind]; + + if (!ouroptarg) + exit(1); + + strncpy(host, ouroptarg, sizeof(host)); + } + break; + + case 'f': + if (rflag) { + printf("Only one of -r and -f allowed\n"); + exit(1); + } + fflag = 1; + + if (++ouroptind == argc) + exit(1); + + ouroptarg = argv[ouroptind]; + + if (!ouroptarg) + exit(1); + + strncpy(name, ouroptarg, sizeof(name)); + break; + + case 'p': + pflag = 1; + break; + } else + i = 0; + if (!i) { + ouroptarg = argv[ouroptind++]; + strncpy(name, ouroptarg, sizeof(name)); + break; + } + } + + for (t = sysconf(_SC_OPEN_MAX); t > 2; t--) + close(t); + +#ifdef TIOCNXCL + /* BSDism: not sure how to rewrite for POSIX. rja */ + ioctl(0, TIOCNXCL, 0); /* set non-exclusive use of tty */ +#endif + + /* get original termio attributes */ + if (tcgetattr(STDIN_FILENO, &attr) != 0) + return (-1); + +/* If talking to an rlogin process, propagate the terminal type and baud rate + across the network. */ + if (rflag) + doremoteterm(term); + +/* Force termios portable control characters to the system default values as +specified in termios.h. This should help the one-time password login feel the +same as the vendor-supplied login. Common extensions are also set for +completeness, but these are set within appropriate defines for portability. */ + +#define CONTROL(x) (x - 64) + +#ifdef VEOF +#ifdef CEOF + attr.c_cc[VEOF] = CEOF; +#else /* CEOF */ + attr.c_cc[VEOF] = CONTROL('D'); +#endif /* CEOF */ +#endif /* VEOF */ +#ifdef VEOL +#ifdef CEOL + attr.c_cc[VEOL] = CEOL; +#else /* CEOL */ + attr.c_cc[VEOL] = CONTROL('J'); +#endif /* CEOL */ +#endif /* VEOL */ +#ifdef VERASE +#ifdef CERASE + attr.c_cc[VERASE] = CERASE; +#else /* CERASE */ + attr.c_cc[VERASE] = CONTROL('H'); +#endif /* CERASE */ +#endif /* VERASE */ +#ifdef VINTR +#ifdef CINTR + attr.c_cc[VINTR] = CINTR; +#else /* CINTR */ + attr.c_cc[VINTR] = CONTROL('C'); +#endif /* CINTR */ +#endif /* VINTR */ +#ifdef VKILL +#ifdef CKILL + attr.c_cc[VKILL] = CKILL; +#else /* CKILL */ + attr.c_cc[VKILL] = CONTROL('U'); +#endif /* CKILL */ +#endif /* VKILL */ +#ifdef VQUIT +#ifdef CQUIT + attr.c_cc[VQUIT] = CQUIT; +#else /* CQUIT */ + attr.c_cc[VQUIT] = CONTROL('\\'); +#endif /* CQUIT */ +#endif /* VQUIT */ +#ifdef VSUSP +#ifdef CSUSP + attr.c_cc[VSUSP] = CSUSP; +#else /* CSUSP */ + attr.c_cc[VSUSP] = CONTROL('Z'); +#endif /* CSUSP */ +#endif /* VSUSP */ +#ifdef VSTOP +#ifdef CSTOP + attr.c_cc[VSTOP] = CSTOP; +#else /* CSTOP */ + attr.c_cc[VSTOP] = CONTROL('S'); +#endif /* CSTOP */ +#endif /* VSTOP */ +#ifdef VSTART +#ifdef CSTART + attr.c_cc[VSTART] = CSTART; +#else /* CSTART */ + attr.c_cc[VSTART] = CONTROL('Q'); +#endif /* CSTART */ +#endif /* VSTART */ +#ifdef VDSUSP +#ifdef CDSUSP + attr.c_cc[VDSUSP] = CDSUSP; +#else /* CDSUSP */ + attr.c_cc[VDSUSP] = 0; +#endif /* CDSUSP */ +#endif /* VDSUSP */ +#ifdef VEOL2 +#ifdef CEOL2 + attr.c_cc[VEOL2] = CEOL2; +#else /* CEOL2 */ + attr.c_cc[VEOL2] = 0; +#endif /* CEOL2 */ +#endif /* VEOL2 */ +#ifdef VREPRINT +#ifdef CRPRNT + attr.c_cc[VREPRINT] = CRPRNT; +#else /* CRPRNT */ + attr.c_cc[VREPRINT] = 0; +#endif /* CRPRNT */ +#endif /* VREPRINT */ +#ifdef VWERASE +#ifdef CWERASE + attr.c_cc[VWERASE] = CWERASE; +#else /* CWERASE */ + attr.c_cc[VWERASE] = 0; +#endif /* CWERASE */ +#endif /* VWERASE */ +#ifdef VLNEXT +#ifdef CLNEXT + attr.c_cc[VLNEXT] = CLNEXT; +#else /* CLNEXT */ + attr.c_cc[VLNEXT] = 0; +#endif /* CLNEXT */ +#endif /* VLNEXT */ + + attr.c_lflag |= ICANON; /* enable canonical input processing */ + attr.c_lflag &= ~ISIG; /* disable INTR, QUIT,& SUSP signals */ + attr.c_lflag |= (ECHO | ECHOE); /* enable echo and erase */ +#ifdef ONLCR + /* POSIX does not specify any output processing flags, but the usage below + is SVID compliant and is generally portable to modern versions of UNIX. */ + attr.c_oflag |= ONLCR; /* map CR to CRNL on output */ +#endif +#ifdef ICRNL + attr.c_iflag |= ICRNL; +#endif /* ICRNL */ + + attr.c_oflag |= OPOST; + attr.c_lflag |= ICANON; /* enable canonical input */ + attr.c_lflag |= ECHO; + attr.c_lflag |= ECHOE; /* enable ERASE character */ + attr.c_lflag |= ECHOK; /* enable KILL to delete line */ + attr.c_cflag |= HUPCL; /* hangup on close */ + + /* Set revised termio attributes */ + if (tcsetattr(STDIN_FILENO, TCSANOW, &attr)) + return (-1); + + atexit(catchexit); + + tty = ttyname(0); + + if (tty == (char *) 0 || *tty == '\0') + tty = "UNKNOWN"; /* was: "/dev/tty??" */ + +#if HAVE_SETVBUF && defined(_IONBF) +#if SETVBUF_REVERSED + setvbuf(stdout, _IONBF, NULL, 0); + setvbuf(stderr, _IONBF, NULL, 0); +#else /* SETVBUF_REVERSED */ + setvbuf(stdout, NULL, _IONBF, 0); + setvbuf(stderr, NULL, _IONBF, 0); +#endif /* SETVBUF_REVERSED */ +#endif /* HAVE_SETVBUF && defined(_IONBF) */ + +#ifdef DEBUG + syslog(LOG_DEBUG, "tty = %s", tty); +#endif /* DEBUG */ + +#ifdef HAVE_LOGIN_ENVFILE + { + FILE *f; + + if (f = fopen(HAVE_LOGIN_ENVFILE, "r")) { + char line[128], *c, *c2; + + while(fgets(line, sizeof(line)-1, f)) { + c = line; + while(*c && (isalnum(*c) || (*c == '_'))) c++; + if (*c == '=') { + *(c++) = 0; + if (c2 = strchr(c, ';')) + *c2 = 0; + if (c2 = strchr(c, '\n')) + *c2 = 0; + if (c2 = strchr(c, ' ')) + continue; + if (c2 = strchr(c, '\t')) + continue; + if (!strcmp(line, "TZ")) + continue; + if (setenv(line, c, 1) < 0) { + fprintf(stderr, "setenv() failed -- environment full?\n"); + break; + } + } + } + fclose(f); + } + } +#endif /* HAVE_LOGIN_ENVFILE */ + + t = 0; + invalid = TRUE; + af_pwok = opieaccessfile(host); + + if (name[0]) + if (name[0] == '-') { + fprintf(stderr, "User names can't start with '-'.\n"); + syslog(LOG_AUTH, "Attempt to use invalid username: %s.", name); + exit(1); + } else + invalid = lookupuser(); + + do { + /* If remote login take given name, otherwise prompt user for something. */ + if (invalid && !name[0]) { + getloginname(); + invalid = lookupuser(); + } +#ifdef DEBUG + syslog(LOG_DEBUG, "login name is +%s+, of length %d, [0] = %d", name, strlen(name), name[0]); +#endif /* DEBUG */ + + if (fflag) { + uid = getuid(); + + if (uid != 0 && uid != thisuser.pw_uid) + fflag = 0; + /* Disallow automatic login for root. */ + if (thisuser.pw_uid == 0) + fflag = 0; + } + if (feof(stdin)) + exit(0); + + /* If no remote login authentication and a password exists for this user, + prompt for and verify a password. */ + if (!fflag && (rflag < 1) && *thisuser.pw_passwd) { +#ifdef DEBUG + syslog(LOG_DEBUG, "login name is +%s+, of length %d, [0] = %d\n", name, strlen(name), name[0]); +#endif /* DEBUG */ + + /* Attempt a one-time password challenge */ + i = opiechallenge(&opie, name, opieprompt); + + if ((i < 0) || (i > 1)) { + syslog(LOG_ERR, "error: opiechallenge() returned %d, errno=%d!\n", i, errno); + fprintf(stderr, "System error; can't issue challenge!\n"); + otpok = 0; + } else { + printf("%s\n", opieprompt); + otpok = 1; + } + + if (!memcmp(&thisuser, &nouser, sizeof(thisuser))) + if (host[0]) + syslog(LOG_WARNING, "Invalid login attempt for %s on %s from %s.", + name, tty, host); + else + syslog(LOG_WARNING, "Invalid login attempt for %s on %s.", + name, tty); + + pwok = af_pwok && opiealways(thisuser.pw_dir); +#if DEBUG + syslog(LOG_DEBUG, "af_pwok = %d, pwok = %d", af_pwok, pwok); +#endif /* DEBUG */ + + if (!pwok && !otpok) { + fprintf(stderr, "Can't authenticate %s!\n"); + continue; + } + +#if NEW_PROMPTS + if (otpok) + printf("Response"); + if (otpok && pwok) + printf(" or "); + if (pwok) + printf("Password"); + printf(": "); + if (!opiereadpass(buf, sizeof(buf), !pwok)) + invalid = TRUE; +#else /* NEW_PROMPTS */ + if (!pwok) + printf("(OTP response required)\n"); + printf("Password:"); + fflush(stdout); + if (!opiereadpass(buf, sizeof(buf), 0)) + invalid = TRUE; +#endif /* NEW_PROMPTS */ + + if (!buf[0] && otpok) { + pwok = 0; + /* Null line entered, so display appropriate prompt & flush current + data. */ +#if NEW_PROMPTS + printf("Response: "); +#else /* NEW_PROMPTS */ + printf(" (echo on)\nPassword:"); +#endif /* NEW_PROMPTS */ + if (!opiereadpass(buf, sizeof(buf), 1)) + invalid = TRUE; + } + + if (otpok) { + i = opiegetsequence(&opie); + opiepassed = !opieverify(&opie, buf); + +#ifdef DEBUG + syslog(LOG_DEBUG, "opiepassed = %d", opiepassed); +#endif /* DEBUG */ + } + + if (!invalid) { + if (otpok && opiepassed) { + if (i < 10) { + printf("Warning: Re-initialize your OTP information"); + if (i < 5) + printf(" NOW!"); + printf("\n"); + } + } else { + if (pwok) { + pp = crypt(buf, thisuser.pw_passwd); + invalid = strcmp(pp, thisuser.pw_passwd); + } else + invalid = TRUE; + } + } + } + + /* If user not super-user, check for logins disabled. */ + if (thisuser.pw_uid) { + if (nlfd = fopen(NO_LOGINS_FILE, "r")) { + while ((c = getc(nlfd)) != EOF) + putchar(c); + fflush(stdout); + sleep(5); + exit(0); + } + } + /* If valid so far and root is logging in, see if root logins on this + terminal are permitted. */ + if (!invalid && !thisuser.pw_uid && !rootterm(tty)) { + if (host[0]) + syslog(LOG_CRIT, "ROOT LOGIN REFUSED ON %s FROM %.*s", + tty, HMAX, host); + else + syslog(LOG_CRIT, "ROOT LOGIN REFUSED ON %s", tty); + invalid = TRUE; + } + /* If invalid, then log failure attempt data to appropriate system + logfiles and close the connection. */ + if (invalid) { + printf("Login incorrect\n"); + if (host[0]) + syslog(LOG_ERR, "LOGIN FAILURE ON %s FROM %.*s, %.*s", + tty, HMAX, host, sizeof(name), name); + else + syslog(LOG_ERR, "LOGIN FAILURE ON %s, %.*s", + tty, sizeof(name), name); + if (++t >= 5) + exit(1); + } + if (*thisuser.pw_shell == '\0') + thisuser.pw_shell = "/bin/sh"; + if ((chdir(thisuser.pw_dir) < 0) && !invalid) { + if (chdir("/") < 0) { + printf("No directory!\n"); + invalid = TRUE; + } else { + printf("No directory! %s\n", "Logging in with HOME=/"); + strcpy(thisuser.pw_dir, "/"); + } + } + /* Remote login invalid must have been because of a restriction of some + sort, no extra chances. */ + if (invalid) { + if (!usererr) + exit(1); + name[0] = 0; + } + } + while (invalid); + /* Committed to login -- turn off timeout */ + alarm(0); + +#ifdef QUOTA + if (quota(Q_SETUID, thisuser.pw_uid, 0, 0) < 0 && errno != EINVAL) { + if (errno == EUSERS) + printf("%s.\n%s.\n", "Too many users logged on already", + "Try again later"); + else + if (errno == EPROCLIM) + printf("You have too many processes running.\n"); + else + perror("quota (Q_SETUID)"); + sleep(5); + exit(0); + } +#endif + + if (opielogin(tty, name, host)) + syslog(LOG_ERR, "can't record login: tty %s, name %s, host %s", tty, name, host); + + quietlog = !access(QUIET_LOGIN_FILE, F_OK); + +#if HAVE_LASTLOG_H + { + int f; + + if ((f = open(lastlog, O_RDWR)) >= 0) { + struct lastlog ll; + + lseek(f, (long)thisuser.pw_uid * sizeof(struct lastlog), 0); + + if ((sizeof(ll) == read(f, (char *) &ll, sizeof(ll))) && + (ll.ll_time != 0) && (!quietlog)) { + printf("Last login: %.*s ", + 24 - 5, (char *) ctime(&ll.ll_time)); + if (*ll.ll_host != '\0') + printf("from %.*s\n", sizeof(ll.ll_host), ll.ll_host); + else + printf("on %.*s\n", sizeof(ll.ll_line), ll.ll_line); + } + lseek(f, (long)thisuser.pw_uid * sizeof(struct lastlog), 0); + + time(&ll.ll_time); + strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); + strncpy(ll.ll_host, host, sizeof(ll.ll_host)); + write(f, (char *) &ll, sizeof ll); + close(f); + } + } +#endif /* HAVE_LASTLOG_H */ + + chown(tty, thisuser.pw_uid, TTYGID(thisuser.pw_gid)); + +#ifdef TIOCSWINSZ +/* POSIX does not specify any interface to set/get window sizes, so this is +not portable. It should work on most recent BSDish systems and the defines +should protect it on older System Vish systems. It does work under Solaris +2.4, though it isn't clear how many other SVR4 systems support it. I'd be +interested in hearing of a more portable approach. rja */ + if (!hflag && !rflag) + ioctl(0, TIOCSWINSZ, &win); /* set window size to 0,0,0,0 */ +#endif + + chmod(tty, 0622); + setgid(thisuser.pw_gid); + initgroups(name, thisuser.pw_gid); + +#ifdef QUOTA + quota(Q_DOWARN, thisuser.pw_uid, (dev_t) - 1, 0); +#endif + +#ifdef PERMSFILE + home = thisuser.pw_dir; + permsfile(name, tty, thisuser.pw_uid, thisuser.pw_gid); + fflush(stderr); +#endif /* PERMSFILE */ + + setuid(thisuser.pw_uid); + + /* destroy environment unless user has asked to preserve it */ + if (!pflag) + environ = envinit; + setenv("HOME", thisuser.pw_dir, 1); + setenv("SHELL", thisuser.pw_shell, 1); + if (!term[0]) { +#if HAVE_GETTTYNAM +/* + * The getttynam() call and the ttyent structure first appeared in 4.3 BSD. + * They are not portable to System V systems such as Solaris 2.x. + * rja + */ + register struct ttyent *t; + register char *c; + + if (c = strrchr(tty, '/')) + c++; + else + c = tty; + + if (t = getttynam(c)) + strncpy(term, t->ty_type, sizeof(term)); + else +#endif /* HAVE_GETTTYNAM */ + strcpy(term, "unknown"); + } + + setenv("USER", name, 1); + setenv("LOGNAME", name, 1); + setenv("PATH", DEFAULT_PATH, 0); + if (term[0]) { +#ifdef DEBUG + syslog(LOG_DEBUG, "setting TERM=%s", term); +#endif /* DEBUG */ + setenv("TERM", term, 1); + } + +#ifdef HAVE_LOGIN_ENVFILE + { + FILE *f; + + if (f = fopen(HAVE_LOGIN_ENVFILE, "r")) { + char line[128], *c, *c2; + + while(fgets(line, sizeof(line)-1, f)) { + c = line; + while(*c && (isalnum(*c) || (*c == '_'))) c++; + if (*c == '=') { + *(c++) = 0; + if (c2 = strchr(c, ';')) + *c2 = 0; + if (c2 = strchr(c, '\n')) + *c2 = 0; + if (c2 = strchr(c, ' ')) + continue; + if (c2 = strchr(c, '\t')) + continue; + if (setenv(line, c, 0) < 0) { + fprintf(stderr, "setenv() failed -- environment full?\n"); + break; + } + } + } + fclose(f); + } + } +#endif /* HAVE_LOGIN_ENVFILE */ + + if ((namep = strrchr(thisuser.pw_shell, '/')) == NULL) + namep = thisuser.pw_shell; + else + namep++; + strcat(minusnam, namep); + if (tty[sizeof("tty") - 1] == 'd') + syslog(LOG_INFO, "DIALUP %s, %s", tty, name); + if (!thisuser.pw_uid) + if (host[0]) + syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s", tty, HMAX, host); + else + syslog(LOG_NOTICE, "ROOT LOGIN %s", tty); +#if !HAVE_MOTD_IN_PROFILE + if (!quietlog) { + FILE *mf; + register c; + + signal(SIGINT, catch); + if ((mf = fopen(MOTD_FILE, "r")) != NULL) { + while ((c = getc(mf)) != EOF && !stopmotd) + putchar(c); + fclose(mf); + } + signal(SIGINT, SIG_IGN); + } +#endif /* !HAVE_MOTD_IN_PROFILE */ +#if !HAVE_MAILCHECK_IN_PROFILE + if (!quietlog) { + struct stat st; + char buf[128]; + int len; + + strncpy(buf, PATH_MAIL, sizeof(buf) - 2); + buf[sizeof(buf) - 2] = 0; + + len = strlen(buf); + if (*(buf + len - 1) != '/') { + *(buf + len) = '/'; + *(buf + len + 1) = 0; + } + + strcat(buf, name); +#if DEBUG + syslog(LOG_DEBUG, "statting %s", buf); +#endif /* DEBUG */ + if (!stat(buf, &st) && st.st_size) + printf("You have %smail.\n", + (st.st_mtime > st.st_atime) ? "new " : ""); + } +#endif /* !HAVE_MAILCHECK_IN_PROFILE */ + signal(SIGALRM, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGTSTP, SIG_IGN); + + attr.c_lflag |= (ISIG | IEXTEN); + + catchexit(); + execlp(thisuser.pw_shell, minusnam, 0); + perror(thisuser.pw_shell); + printf("No shell\n"); + exit(0); +} diff --git a/contrib/opie/opiepasswd.1 b/contrib/opie/opiepasswd.1 new file mode 100644 index 0000000..1fd9123 --- /dev/null +++ b/contrib/opie/opiepasswd.1 @@ -0,0 +1,176 @@ +.\" opiepasswd.1: Manual page for the opiepasswd(1) program. +.\" +.\" %%% portions-copyright-cmetz +.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights +.\" Reserved. The Inner Net License Version 2 applies to these portions of +.\" the software. +.\" You should have received a copy of the license with this software. If +.\" you didn't get a copy, you may request one from . +.\" +.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan +.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned +.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +.\" License Agreement applies to this software. +.\" +.\" History: +.\" +.\" Modified by cmetz for OPIE 2.3. Added -f flag documentation. +.\" Updated console example. +.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation. +.\" Modified at NRL for OPIE 2.0. +.\" Written at Bellcore for the S/Key Version 1 software distribution +.\" (keyinit.1). +.\" +.ll 6i +.pl 10.5i +.lt 6.0i +.TH OPIEPASSWD 1 "January 10, 1995" +.AT 3 +.SH NAME +opiepasswd \- Change or set a user's password for the OPIE authentication +system. + +.SH SYNOPSIS +.B opiepasswd +[\-v] [\-h] [\-c|\-d] [\-f] +.sp 0 +[\-n +.I inital_sequence_number +] +[\-s +.I seed +] [ +.I user_name +] + +.SH DESCRIPTION +.I opiepasswd +will initialize the system information to allow one to use OPIE to login. +.I opiepasswd +is downward compatible with the keyinit(1) program from the +Bellcore S/Key Version 1 distribution. + +.SH OPTIONS +.TP +.TP +.B \-v +Display the version number and compile-time options, then exit. +.TP +.B \-h +Display a brief help message and exit. +.TP +.B \-c +Set console mode where the user is expected to have secure access to the +system. In console mode, you will be asked to input your password directly +instead of having to use an OPIE calculator. If you do not have secure access +to the system (i.e., you are not on the system's console), you are +volunteering your password to attackers by using this mode. +.TP +.B \-d +Disable OTP logins to the specified account. +.TP +.B \-f +Force +.I opiepasswd +to continue, even where it normally shouldn't. This is currently used to +force opiepasswd to operate in "console" mode even from terminals it believes +to be insecure. It can also allow users to disclose their secret pass phrases +to attackers. Use of the -f flag may be disabled by compile-time option in +your particular build of OPIE. +.TP +.B \-n +Manually specify the initial sequence number. The default is 499. +.TP +.B \-s +Specify a non-random seed. The default is to generate a "random" seed using +the first two characters of the host name and five pseudo-random digits. +.SH EXAMPLE +Using +.I opiepasswd +from the console: +.LP +.sp 0 +wintermute$ opiepasswd \-c +.sp 0 +Updating kebe: +.sp 0 +Reminder \- Only use this method from the console; NEVER from remote. If you +.sp 0 +are using telnet, xterm, or a dial\-in, type ^C now or exit with no password. +.sp 0 +Then run opiepasswd without the \-c parameter. +.sp 0 +Using MD5 to compute responses. +.sp 0 +Enter old secret pass phrase: +.sp 0 +Enter new secret pass phrase: +.sp 0 +Again new secret pass phrase: +.sp 0 + +.sp 0 +ID kebe OPIE key is 499 be93564 +.sp 0 +CITE JAN GORY BELA GET ABED +.sp 0 +wintermute$ +.LP +Using +.I opiepasswd +from remote: +.LP +.sp 0 +wintermute$ opiepasswd +.sp 0 +Updating kebe: +.sp 0 +Reminder: You need the response from your OPIE calculator. +.sp 0 +Old secret password: +.sp 0 + otp-md5 482 wi93563 +.sp 0 + Response: FIRM BERN THEE DUCK MANN AWAY +.sp 0 +New secret password: +.sp 0 + otp-md5 499 wi93564 +.sp 0 + Response: SKY FAN BUG HUFF GUS BEAT +.sp 0 + +.sp 0 +ID kebe OPIE key is 499 wi93564 +.sp 0 +SKY FAN BUG HUFF GUS BEAT +.sp 0 +wintermute$ +.LP +.SH FILES +.TP +/etc/opiekeys -- database of key information for the OPIE system. + +.SH SEE ALSO +.BR passwd (1), +.BR opie (4), +.BR opiekey (1), +.BR opieinfo (1), +.BR opiesu (1), +.BR opielogin (1), +.BR opieftpd (8), +.BR opiekeys (5), +.BR opieaccess (5) + +.SH AUTHOR +Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden +of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and +Craig Metz. + +S/Key is a trademark of Bell Communications Research (Bellcore). + +.SH CONTACT +OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join, +send an email request to: +.sp +skey-users-request@thumper.bellcore.com diff --git a/contrib/opie/opiepasswd.c b/contrib/opie/opiepasswd.c new file mode 100644 index 0000000..719b68f --- /dev/null +++ b/contrib/opie/opiepasswd.c @@ -0,0 +1,429 @@ +/* opiepasswd.c: Add/change an OTP password in the key database. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Got of some variables and made some + local to where they're used. Split out the finishing code. Use + opielookup() instead of opiechallenge() to find user. Three + strikes on prompts. Use opiepasswd()'s new calling + convention. Changed OPIE_PASS_{MAX,MIN} to + OPIE_SECRET_{MAX,MIN}. Handle automatic reinits happenning + below us. Got rid of unneeded headers. Use new opieatob8() + return value convention. Added -f flag. Added SHA support. + Modified by cmetz for OPIE 2.22. Finally got rid of the lock + filename kluge by implementing refcounts for locks. + Use opiepasswd() to update key file. Error if we can't + write to the key file. Check for minimum seed length. + Modified at NRL for OPIE 2.2. Changed opiestrip_crlf to + opiestripcrlf. Check opiereadpass() return value. + Minor optimization. Change calls to opiereadpass() to + use echo arg. Use opiereadpass() where we can. + Make everything static. Ifdef around some headers. + Changed use of gethostname() to uname(). Got rid of + the need for buf[]. Properly check return value of + opieatob8. Check seed length. Always generate proper- + length seeds. + Modified at NRL for OPIE 2.1. Minor autoconf changes. + Modified heavily at NRL for OPIE 2.0. + Written at Bellcore for the S/Key Version 1 software distribution + (skeyinit.c). +*/ +#include "opie_cfg.h" + +#if HAVE_PWD_H +#include +#endif /* HAVE_PWD_H */ +#include +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#include +#include +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#if HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ + +#include "opie.h" + +#define MODE_DEFAULT 0 +#define MODE_CONSOLE 1 +#define MODE_DISABLE 2 + +extern int optind; +extern char *optarg; + +char *algnames[] = { NULL, NULL, NULL, "SHA-1", "MD4", "MD5" }; +char *algids[] = { NULL, NULL, NULL, "sha1", "md4", "md5" }; + +static VOIDRET usage FUNCTION((myname), char *myname) +{ + fprintf(stderr, "usage: %s [-v] [-h] [-c|-d] [-f] [-n initial_sequence_number]\n [-s seed] [username]\n", myname); + exit(1); +} + +static VOIDRET finish FUNCTION((name), char *name) +{ + struct opie opie; + char buf[OPIE_RESPONSE_MAX + 1]; + + if (name) { + if (opiechallenge(&opie, name, buf)) { + fprintf(stderr, "Error verifying database.\n"); + finish(NULL); + } + printf("\nID %s ", opie.opie_principal); + if (opie.opie_val && (opie.opie_val[0] == '*')) { + printf("is disabled.\n"); + finish(NULL); + } + printf("OTP key is %d %s\n", opie.opie_n, opie.opie_seed); + { + char key[8]; + if (!opieatob8(key, opie.opie_val)) { + fprintf(stderr, "Error verifying key -- possible database corruption.\n"); + finish(NULL); + } + printf("%s\n", opiebtoe(buf, key)); + } + } + + while(!opieunlock()); + exit(name ? 0 : 1); +} + +int main FUNCTION((argc, argv), int argc AND char *argv[]) +{ + struct opie opie; + int rval, n = 499, i, mode = MODE_DEFAULT, force = 0; + char seed[18]; + struct passwd *pp; + + memset(seed, 0, sizeof(seed)); + + if (!(pp = getpwuid(getuid()))) { + fprintf(stderr, "Who are you?"); + return 1; + } + + while ((i = getopt(argc, argv, "fhvcn:s:")) != EOF) { + switch (i) { + case 'v': + opieversion(); + case 'f': +#if INSECURE_OVERRIDE + force = 1; +#else /* INSECURE_OVERRIDE */ + fprintf(stderr, "Sorry, but the -f option is not supported by this build of OPIE.\n"); +#endif /* INSECURE_OVERRIDE */ + break; + case 'c': + mode = MODE_CONSOLE; + break; + case 'd': + mode = MODE_DISABLE; + break; + case 'n': + i = atoi(optarg); + if (!(i > 0 && i < 10000)) { + printf("Sequence numbers must be > 0 and < 10000\n"); + finish(NULL); + } + n = i; + break; + case 's': + i = strlen(optarg); + if ((i > OPIE_SEED_MAX) || (i < OPIE_SEED_MIN)) { + printf("Seeds must be between %d and %d characters long.\n", + OPIE_SEED_MIN, OPIE_SEED_MAX); + finish(NULL); + } + strncpy(seed, optarg, sizeof(seed)); + seed[sizeof(seed) - 1] = 0; + break; + default: + usage(argv[0]); + } + } + + if (argc - optind >= 1) { + if (strcmp(argv[optind], pp->pw_name)) { + if (getuid()) { + printf("Only root can change others' passwords.\n"); + exit(1); + } + if ((pp = getpwnam(argv[optind])) == NULL) { + printf("%s: user unknown.\n", argv[optind]); + exit(1); + } + } + } + + opielock(pp->pw_name); + rval = opielookup(&opie, pp->pw_name); + + switch (rval) { + case 0: + printf("Updating %s:\n", pp->pw_name); + break; + case 1: + printf("Adding %s:\n", pp->pw_name); + break; + case 2: + fprintf(stderr, "Error: Can't update key database.\n"); + exit(1); + default: + fprintf(stderr, "Error reading key database\n"); + exit(1); + } + + if (seed[0]) { + i = strlen(seed); + if (i > OPIE_SEED_MAX) { + fprintf(stderr, "Seeds must be less than %d characters long.", OPIE_SEED_MAX); + finish(NULL); + } + if (i < OPIE_SEED_MIN) { + fprintf(stderr, "Seeds must be greater than %d characters long.", OPIE_SEED_MIN); + finish(NULL); + } + } else { + if (!rval) + strcpy(seed, opie.opie_seed); + + if (opienewseed(seed) < 0) { + fprintf(stderr, "Error updating seed.\n"); + finish(NULL); + } + } + + if (opie.opie_seed && opie.opie_seed[0] && !strcmp(opie.opie_seed, seed)) { + fprintf(stderr, "You must use a different seed for the new OTP sequence.\n"); + finish(NULL); + } + + switch(mode) { + case MODE_DEFAULT: + { + char tmp[OPIE_RESPONSE_MAX + 2]; + + printf("You need the response from an OTP generator.\n"); +#if DEBUG + if (!rval) { +#else /* DEBUG */ + if (!rval && getuid()) { +#endif /* DEBUG */ + char oseed[OPIE_SEED_MAX + 1]; + int on; + + if (opiechallenge(&opie, pp->pw_name, tmp)) { + fprintf(stderr, "Error issuing challenge.\n"); + finish(NULL); + } + on = opiegetsequence(&opie); + { + char *c; + if (c = strrchr(tmp, ' ')) + strncpy(oseed, c + 1, sizeof(oseed)); + else { +#if DEBUG + fprintf(stderr, "opiepasswd: bogus challenge\n"); +#endif /* DEBUG */ + finish(NULL); + } + } + printf("Old secret pass phrase:\n\t%s\n\tResponse: ", tmp); + if (!opiereadpass(tmp, sizeof(tmp), 1)) + tmp[0] = 0; + i = opieverify(&opie, tmp); + if (!tmp[0]) { + fprintf(stderr, "Error reading response.\n"); + finish(NULL); + } + if (i) { + fprintf(stderr, "Error verifying response.\n"); +#if DEBUG + fprintf(stderr, "opiepasswd: opieverify() returned %d\n", i); +#endif /* DEBUG */ + finish(NULL); + } + { + char nseed[OPIE_SEED_MAX + 1]; + int nn; + + if (opiechallenge(&opie, pp->pw_name, tmp)) { + fprintf(stderr, "Error verifying database.\n"); + finish(NULL); + } + + nn = opiegetsequence(&opie); + { + char *c; + if (c = strrchr(tmp, ' ')) + strncpy(nseed, c + 1, sizeof(nseed)); + else { +#if DEBUG + fprintf(stderr, "opiepasswd: bogus challenge\n"); +#endif /* DEBUG */ + finish(NULL); + } + } + + opieverify(&opie, ""); + nn++; + + if ((nn != on) || strcmp(oseed, nseed)) + finish(pp->pw_name); + } + } + printf("New secret pass phrase:"); + for (i = 0;; i++) { + if (i > 2) + finish(NULL); + printf("\n\totp-%s %d %s\n\tResponse: ", algids[MDX], n, seed); + if (!opiereadpass(tmp, sizeof(tmp), 1)) { + fprintf(stderr, "Error reading response.\n"); + finish(NULL); + } + if (tmp[0] == '?') { + printf("Enter the response from your OTP calculator: \n"); + continue; + } + if (tmp[0] == '\0') { + fprintf(stderr, "Secret pass phrase unchanged.\n"); + finish(NULL); + } + + if (!(rval = opiepasswd(&opie, 0, pp->pw_name, n, seed, tmp))) + finish(pp->pw_name); + + if (rval < 0) { + fprintf(stderr, "Error updating key database.\n"); + finish(NULL); + } + printf("\tThat is not a valid OTP response.\n"); + } + } + break; + case MODE_CONSOLE: + { + char passwd[OPIE_SECRET_MAX + 1], passwd2[OPIE_SECRET_MAX + 1]; + /* Get user's secret password */ + fprintf(stderr, "Only use this method from the console; NEVER from remote. If you are using\n"); + fprintf(stderr, "telnet, xterm, or a dial-in, type ^C now or exit with no password.\n"); + fprintf(stderr, "Then run opiepasswd without the -c parameter.\n"); + if (opieinsecure()) { + fprintf(stderr, "Sorry, but you don't seem to be on the console or a secure terminal.\n"); + if (force) + fprintf(stderr, "Warning: Continuing could disclose your secret pass phrase to an attacker!\n"); + else + finish(NULL); + }; + printf("Using %s to compute responses.\n", algnames[MDX]); + if (!rval && getuid()) { + printf("Enter old secret pass phrase: "); + if (!opiereadpass(passwd, sizeof(passwd), 0)) { + fprintf(stderr, "Error reading secret pass phrase!\n"); + finish(NULL); + } + if (!passwd[0]) { + fprintf(stderr, "Secret pass phrase unchanged.\n"); + finish(NULL); + } + { + char key[8]; + char tbuf[OPIE_RESPONSE_MAX + 1]; + + if (opiekeycrunch(MDX, key, opie.opie_seed, passwd) != 0) { + fprintf(stderr, "%s: key crunch failed. Secret pass phrase unchanged\n", argv[0]); + finish(NULL); + } + memset(passwd, 0, sizeof(passwd)); + i = opie.opie_n - 1; + while (i-- != 0) + opiehash(key, MDX); + opiebtoe(tbuf, key); + if (opieverify(&opie, tbuf)) { + fprintf(stderr, "Sorry.\n"); + finish(NULL); + } + } + } + for (i = 0;; i++) { + if (i > 2) + finish(NULL); + printf("Enter new secret pass phrase: "); + if (!opiereadpass(passwd, sizeof(passwd), 0)) { + fprintf(stderr, "Error reading secret pass phrase.\n"); + finish(NULL); + } + if (!passwd[0] || feof(stdin)) { + fprintf(stderr, "Secret pass phrase unchanged.\n"); + finish(NULL); + } + if (opiepasscheck(passwd)) { + memset(passwd, 0, sizeof(passwd)); + fprintf(stderr, "Secret pass phrases must be between %d and %d characters long.\n", OPIE_SECRET_MIN, OPIE_SECRET_MAX); + continue; + } + printf("Again new secret pass phrase: "); + if (!opiereadpass(passwd2, sizeof(passwd2), 0)) { + fprintf(stderr, "Error reading secret pass phrase.\n"); + finish(NULL); + } + if (feof(stdin)) { + fprintf(stderr, "Secret pass phrase unchanged.\n"); + finish(NULL); + } + if (!passwd[0] || !strcmp(passwd, passwd2)) + break; + fprintf(stderr, "Sorry, no match.\n"); + } + memset(passwd2, 0, sizeof(passwd2)); + if (opiepasswd(&opie, 1, pp->pw_name, n, seed, passwd)) { + fprintf(stderr, "Error updating key database.\n"); + finish(NULL); + } + finish(pp->pw_name); + } + case MODE_DISABLE: + { + char tmp[4]; + int i; + + for (i = 0;; i++) { + if (i > 2) + finish(NULL); + + printf("Disable %s's OTP access? (yes or no) ", pp->pw_name); + if (!opiereadpass(tmp, sizeof(tmp), 1)) { + fprintf(stderr, "Error reading entry.\n"); + finish(NULL); + } + if (!strcmp(tmp, "no")) + finish(NULL); + if (!strcmp(tmp, "yes")) { + if (opiepasswd(&opie, 0, pp->pw_name, n, seed, NULL)) { + fprintf(stderr, "Error updating key database.\n"); + finish(NULL); + } + finish(pp->pw_name); + } + } + } + } +} diff --git a/contrib/opie/opieserv.1 b/contrib/opie/opieserv.1 new file mode 100644 index 0000000..edde9eb --- /dev/null +++ b/contrib/opie/opieserv.1 @@ -0,0 +1,82 @@ +.\" opieserv.1: Manual page for the opieserv(1) program. +.\" +.\" %%% portions-copyright-cmetz +.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights +.\" Reserved. The Inner Net License Version 2 applies to these portions of +.\" the software. +.\" You should have received a copy of the license with this software. If +.\" you didn't get a copy, you may request one from . +.\" +.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan +.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned +.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +.\" License Agreement applies to this software. +.\" +.\" History: +.\" +.\" Created by cmetz for OPIE 2.2 from opiegen.1. +.\" +.ll 6i +.pl 10.5i +.lt 6.0i +.TH OPIEKEY 1 "February 20, 1996" +.AT 3 +.SH NAME +opieserv \- Example OPIE-based OTP server + +.SH SYNOPSIS +.B opieserv +.sp 0 +[ +.I principal +] +.sp 0 + +.SH DESCRIPTION +.I opieserv +takes an OTP principal (e.g., a user name) from either the command line or +standard input and returns a current OTP challenge for that principal. It then +reads an OTP response to that challenge from standard input and displays a +message and returns a value to indicate either success (exit value = 0) or +failure (exit value = 1). It is intended as an example for programmers +of how a simple OTP server can be built. + +.SH EXAMPLE +.sp 0 +wintermute$ opieserv kebe +.sp 0 +otp-md5 495 wi01309 +.sp 0 +Response: +.sp 0 +User verified. +.sp 0 +wintermute$ +.LP + +.SH SEE ALSO +.BR opiegen (1), +.BR opiekey (1), +.BR opie (4), +.BR opiepasswd (1), +.BR opieinfo (1), +.BR opiesu (1), +.BR opielogin (1), +.BR opieftpd (8), +.BR opiekeys (5), +.BR opieaccess (5) + +.SH AUTHOR +The opieserv1) program was created by Craig Metz for OPIE 2.2. + +Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden +of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and +Craig Metz. + +S/Key is a trademark of Bell Communications Research (Bellcore). + +.SH CONTACT +OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join, +send an email request to: +.sp +skey-users-request@thumper.bellcore.com diff --git a/contrib/opie/opieserv.c b/contrib/opie/opieserv.c new file mode 100644 index 0000000..241dbb3 --- /dev/null +++ b/contrib/opie/opieserv.c @@ -0,0 +1,83 @@ +/* opieserv.c: Sample OTP server based on the opiechallenge() and + opieverify() library routines. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Modified by cmetz for OPIE 2.3. Send debug info to syslog. + Created by cmetz for OPIE 2.2. +*/ +#include "opie_cfg.h" +#include +#if DEBUG +#include +#endif /* DEBUG */ +#include "opie.h" + +int main FUNCTION((argc, argv), int argc AND char *argv[]) +{ + struct opie opie; + char *principal; + char buffer[1024]; + char challenge[OPIE_CHALLENGE_MAX+1]; + char response[OPIE_RESPONSE_MAX+1]; + int result; + + if (argc <= 1) { + fputs("Principal: ", stderr); + if (!opiereadpass(buffer, sizeof(buffer)-1, 1)) + fprintf(stderr, "Error reading principal!"); + principal = buffer; + } else { + principal = argv[1]; + } +#if DEBUG + syslog(LOG_DEBUG, "Principal is +%s+", principal); +#endif /* DEBUG */ + + switch (result = opiechallenge(&opie, principal, challenge)) { + case -1: + fputs("System error!\n", stderr); + exit(1); + case 0: + break; + case 1: + fputs("User not found!\n", stderr); + exit(1); + case 2: + fputs("System error!\n", stderr); + exit(1); + default: + fprintf(stderr, "Unknown error %d!\n", result); + exit(1); + }; + + fputs(challenge, stdout); + fputc('\n', stdout); + fflush(stdout); + fputs("Response: ", stderr); + if (!opiereadpass(response, OPIE_RESPONSE_MAX, 1)) { + fputs("Error reading response!\n", stderr); + exit(1); + }; + + switch (result = opieverify(&opie, response)) { + case -1: + fputs("System error!\n", stderr); + exit(1); + case 0: + fputs("User verified.\n", stderr); + exit(0); + case 1: + fputs("Verify failed!\n", stderr); + exit(1); + default: + fprintf(stderr, "Unknown error %d!\n", result); + exit(1); + } +} diff --git a/contrib/opie/opiesu.1 b/contrib/opie/opiesu.1 new file mode 100644 index 0000000..5edf24b --- /dev/null +++ b/contrib/opie/opiesu.1 @@ -0,0 +1,101 @@ +.\" opiesu.c: Manual page for the opiesu(1) program. +.\" +.\" %%% portions-copyright-cmetz +.\" Portions of this software are Copyright 1996 by Craig Metz, All Rights +.\" Reserved. The Inner Net License Version 2 applies to these portions of +.\" the software. +.\" You should have received a copy of the license with this software. If +.\" you didn't get a copy, you may request one from . +.\" +.\" Portions of this software are Copyright 1995 by Randall Atkinson and Dan +.\" McDonald, All Rights Reserved. All Rights under this copyright are assigned +.\" to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +.\" License Agreement applies to this software. +.\" +.\" History: +.\" +.\" Modified by cmetz for OPIE 2.3. Removed statement that opiesu will +.\" only accept OTP responses. +.\" Modified by cmetz for OPIE 2.2. Removed MJR DES documentation. +.\" Modified at NRL for OPIE 2.0. +.\" Documentation for the "-f" option from BSD. +.\" Written at Bellcore for the S/Key Version 1 software distribution +.\" (keysu.1). +.\" +.ll 6i +.pl 10.5i +.lt 6.0i +.TH OPIESU 1 "January 10, 1995" +.AT 3 +.SH NAME +opiesu \- Replacement su(1) program that uses OPIE challenges +.SH SYNOPSIS +.B opiesu +[ \-f ] [ \-c ] [ +.I user_name +] +.SH DESCRIPTION +.I opiesu +is a replacement for the su(1) program that issues OPIE challenges and +uses OPIE responses. It is downward compatible with keysu(1) from the +Bellcore S/Key Version 1 distribution and the su(1) program from the 4.3BSD +Net/2 distribution. +.SH OPTIONS +.TP +.B \-f +If the invoked shell is csh(1), this option prevents it from +reading the ``.cshrc'' file. (The [f] option may be passed as a +shell argument after the login name, so this option is redundant +and obsolescent.) +.TP +.B \-c +Set console mode where the user is expected to have secure access to the +system. In console mode, you will be asked to input your password directly +instead of having to use an OPIE calculator. If you do not have secure access +to the system (i.e., you are not on the system's console), you are +volunteering your password to attackers by using this mode. +.TP +.I user_name +The name of the user to become. +The default is root. +.SH EXAMPLE +.sp 0 +wintermute$ opiesu kebe +.sp 0 +otp-md5 498 wi910502 +.sp 0 +(OTP response required) +.sp 0 +kebe's password: (echo on) +.sp 0 +kebe's password: RARE GLEN HUGH BOYD NECK MOLL +.sp 0 +wintermute# +.LP +.SH FILES +.TP +/etc/opiekeys database of information for OPIE system. +.LP +.SH SEE ALSO +.BR su (1), +.BR opie (4), +.BR opiekey (1), +.BR opieinfo (1), +.BR opiesu (1), +.BR opielogin (1), +.BR opieftpd (8), +.BR opiekeys (5), +.BR opieaccess (5) + +.SH AUTHOR +Bellcore's S/Key was written by Phil Karn, Neil M. Haller, and John S. Walden +of Bellcore. OPIE was created at NRL by Randall Atkinson, Dan McDonald, and +Craig Metz. + +S/Key is a trademark of Bell Communications Research (Bellcore). + +.SH CONTACT +OPIE is discussed on the Bellcore "S/Key Users" mailing list. To join, +send an email request to: +.sp +skey-users-request@thumper.bellcore.com diff --git a/contrib/opie/opiesu.c b/contrib/opie/opiesu.c new file mode 100644 index 0000000..403305b --- /dev/null +++ b/contrib/opie/opiesu.c @@ -0,0 +1,448 @@ +/* opiesu.c: main body of code for the su(1m) program + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Limit the length of TERM on full login. + Use HAVE_SULOG instead of DOSULOG. + Modified by cmetz for OPIE 2.2. Don't try to clear non-blocking I/O. + Use opiereadpass(). Minor speedup. Removed termios manipulation + -- that's opiereadpass()'s job. Change opiereadpass() calls + to add echo arg. Removed useless strings (I don't think that + removing the ucb copyright one is a problem -- please let me + know if I'm wrong). Use FUNCTION declaration et al. Ifdef + around some headers. Make everything static. Removed + closelog() prototype. Use the same catchexit() trickery as + opielogin. + Modified at NRL for OPIE 2.2. Changed opiestrip_crlf to + opiestripcrlf. + Modified at NRL for OPIE 2.1. Added struct group declaration. + Added Solaris(+others?) sulog capability. Symbol changes + for autoconf. Removed des_crypt.h. File renamed to + opiesu.c. Symbol+misc changes for autoconf. Added bletch + for setpriority. + Modified at NRL for OPIE 2.02. Added SU_STAR_CHECK (turning a bug + into a feature ;). Fixed Solaris shadow password problem + introduced in OPIE 2.01 (the shadow password structure is + spwd, not spasswd). + Modified at NRL for OPIE 2.01. Changed password lookup handling + to use a static structure to avoid problems with drain- + bamaged shadow password packages. Always log failures. + Make sure to close syslog by function to avoid problems + with drain bamaged syslog implementations. Log a few + interesting errors. + Modified at NRL for OPIE 2.0. + Modified at Bellcore for the S/Key Version 1 software distribution. + Originally from BSD. +*/ + +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + +#include "opie_cfg.h" + +#include +#if HAVE_PWD_H +#include +#endif /* HAVE_PWD_H */ +#include +#include +#include +#if HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H +#if TIME_WITH_SYS_TIME +# include +# include +#else /* TIME_WITH_SYS_TIME */ +#if HAVE_SYS_TIME_H +#include +#else /* HAVE_SYS_TIME_H */ +#include +#endif /* HAVE_SYS_TIME_H */ +#endif /* TIME_WITH_SYS_TIME */ +#include +#else /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */ +#if TM_IN_SYS_TIME +#include +#else /* TM_IN_SYS_TIME */ +#include +#endif /* TM_IN_SYS_TIME */ +#endif /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */ +#if HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#include + +#include "opie.h" + +static char userbuf[16] = "USER="; +static char homebuf[128] = "HOME="; +static char shellbuf[128] = "SHELL="; +static char pathbuf[128] = "PATH="; +static char termbuf[32] = "TERM="; +static char *cleanenv[] = {userbuf, homebuf, shellbuf, pathbuf, 0, 0}; +static char *user = "root"; +static char *shell = "/bin/sh"; +static int fulllogin; +static int fastlogin; + +extern char **environ; +static struct passwd thisuser, nouser; + +#if HAVE_SHADOW_H +#include +#endif /* HAVE_SHADOW_H */ + +#if HAVE_CRYPT_H +#include +#endif /* HAVE_CRYPT_H */ + +static VOIDRET catchexit FUNCTION_NOARGS +{ + int i; + closelog(); + for (i = sysconf(_SC_OPEN_MAX); i > 2; i--) + close(i); +} + +/* We allow the malloc()s to potentially leak data out because we can +only call this routine about four times in the lifetime of this process +and the kernel will free all heap memory when we exit or exec. */ +static int lookupuser FUNCTION((name), char *name) +{ + struct passwd *pwd; +#if HAVE_SHADOW + struct spwd *spwd; +#endif /* HAVE_SHADOW */ + + memcpy(&thisuser, &nouser, sizeof(thisuser)); + + if (!(pwd = getpwnam(name))) + return -1; + + thisuser.pw_uid = pwd->pw_uid; + thisuser.pw_gid = pwd->pw_gid; + + if (!(thisuser.pw_name = malloc(strlen(pwd->pw_name) + 1))) + goto lookupuserbad; + strcpy(thisuser.pw_name, pwd->pw_name); + + if (!(thisuser.pw_dir = malloc(strlen(pwd->pw_dir) + 1))) + goto lookupuserbad; + strcpy(thisuser.pw_dir, pwd->pw_dir); + + if (!(thisuser.pw_shell = malloc(strlen(pwd->pw_shell) + 1))) + goto lookupuserbad; + strcpy(thisuser.pw_shell, pwd->pw_shell); + +#if HAVE_SHADOW + if (!(spwd = getspnam(name))) + goto lookupuserbad; + + pwd->pw_passwd = spwd->sp_pwdp; + + endspent(); +#endif /* HAVE_SHADOW */ + + if (!(thisuser.pw_passwd = malloc(strlen(pwd->pw_passwd) + 1))) + goto lookupuserbad; + strcpy(thisuser.pw_passwd, pwd->pw_passwd); + + endpwent(); + +#if SU_STAR_CHECK + return ((thisuser.pw_passwd[0] == '*') || (thisuser.pw_passwd[0] == '#')); +#else /* SU_STAR_CHECK */ + return 0; +#endif /* SU_STAR_CHECK */ + +lookupuserbad: + memcpy(&thisuser, &nouser, sizeof(thisuser)); + return -1; +} + +static VOIDRET lsetenv FUNCTION((ename, eval, buf), char *ename AND char *eval AND char *buf) +{ + register char *cp, *dp; + register char **ep = environ; + + /* this assumes an environment variable "ename" already exists */ + while (dp = *ep++) { + for (cp = ename; *cp == *dp && *cp; cp++, dp++) + continue; + if (*cp == 0 && (*dp == '=' || *dp == 0)) { + strcat(buf, eval); + *--ep = buf; + return; + } + } +} + +#if HAVE_SULOG +static int sulog FUNCTION((status, who), int status AND char *who) +{ + char *from; + char *ttynam; + struct tm *tm; + FILE *f; + time_t now; + + if (who) + from = who; + else + from = Getlogin(); + + if (!strncmp(ttynam = ttyname(2), "/dev/", 5)) + ttynam += 5; + + now = time(NULL); + tm = localtime(&now); + + if (!(f = fopen("/var/adm/sulog", "a"))) { + fprintf(stderr, "Can't update su log!\n"); + exit(1); + } + + fprintf(f, "SU %02d/%02d %02d:%02d %c %s %s-%s\n", + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, + result ? '+' : '-', ttynam, from, user); + fclose(f); +} +#endif /* HAVE_SULOG */ + +int main FUNCTION((argc, argv), int argc AND char *argv[]) +{ + char buf[1000], *p; + struct opie opie; + int i; + char pbuf[256]; + char opieprompt[80]; + int console = 0; + +#define Getlogin() (((p = getlogin()) && *p) ? p : buf) + + for (i = sysconf(_SC_OPEN_MAX); i > 2; i--) + close(i); + + strcat(pathbuf, DEFAULT_PATH); + +again: + if (argc > 1 && strcmp(argv[1], "-f") == 0) { + fastlogin++; + argc--, argv++; + goto again; + } + if (argc > 1 && strcmp(argv[1], "-c") == 0) { + console++; + argc--, argv++; + goto again; + } + if (argc > 1 && strcmp(argv[1], "-") == 0) { + fulllogin++; + argc--; + argv++; + goto again; + } + if (argc > 1 && argv[1][0] != '-') { + user = argv[1]; + argc--; + argv++; + } + + openlog("su", LOG_ODELAY, LOG_AUTH); + atexit(catchexit); + + { + struct passwd *pwd; + + if ((pwd = getpwuid(getuid())) == NULL) { + syslog(LOG_CRIT, "'%s' failed for unknown uid %d on %s", argv[0], getuid(), ttyname(2)); +#if HAVE_SULOG + sulog(0, "unknown"); +#endif /* HAVE_SULOG */ + exit(1); + } + strcpy(buf, pwd->pw_name); + } + + if (lookupuser(user)) { + syslog(LOG_CRIT, "'%s' failed for %s on %s", argv[0], Getlogin(), ttyname(2)); +#if HAVE_SULOG + sulog(0, NULL); +#endif /* HAVE_SULOG */ + fprintf(stderr, "Unknown user: %s\n", user); + exit(1); + } + +/* Implement the BSD "wheel group" su restriction. */ +#if DOWHEEL + /* Only allow those in group zero to su to root? */ + if (thisuser.pw_uid == 0) { + struct group *gr; + if ((gr = getgrgid(0)) != NULL) { + for (i = 0; gr->gr_mem[i] != NULL; i++) + if (strcmp(buf, gr->gr_mem[i]) == 0) + goto userok; + fprintf(stderr, "You do not have permission to su %s\n", user); + exit(1); + } +userok: + ; +#if HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H + setpriority(PRIO_PROCESS, 0, -2); +#endif /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */ + } +#endif /* DOWHEEL */ + + if (!thisuser.pw_passwd[0] || getuid() == 0) + goto ok; + + if (console) { + if (!opiealways(thisuser.pw_dir)) { + fprintf(stderr, "That account requires OTP responses.\n"); + exit(1); + }; + /* Get user's secret password */ + fprintf(stderr, "Reminder - Only use this method from the console; NEVER from remote. If you\n"); + fprintf(stderr, "are using telnet, xterm, or a dial-in, type ^C now or exit with no password.\n"); + fprintf(stderr, "Then run su without the -c parameter.\n"); + if (opieinsecure()) { + fprintf(stderr, "Sorry, but you don't seem to be on the console or a secure terminal.\n"); + exit(1); + }; +#if NEW_PROMPTS + printf("%s's system password: ", thisuser.pw_name); + if (!opiereadpass(pbuf, sizeof(pbuf), 0)) + goto error; +#endif /* NEW_PROMPTS */ + } else { + /* Attempt an OTP challenge */ + i = opiechallenge(&opie, user, opieprompt); + printf("%s\n", opieprompt); +#if NEW_PROMPTS + printf("%s's response: ", thisuser.pw_name); + if (!opiereadpass(pbuf, sizeof(pbuf), 1)) + goto error; +#else /* NEW_PROMPTS */ + printf("(OTP response required)\n"); +#endif /* NEW_PROMPTS */ + fflush(stdout); + }; +#if !NEW_PROMPTS + printf("%s's password: ", thisuser.pw_name); + if (!opiereadpass(pbuf, sizeof(pbuf), 0)) + goto error; +#endif /* !NEW_PROMPTS */ + +#if !NEW_PROMPTS + if (!pbuf[0] && !console) { + /* Null line entered; turn echoing back on and read again */ + printf(" (echo on)\n%s's password: ", thisuser.pw_name); + if (!opiereadpass(pbuf, sizeof(pbuf), 1)) + goto error; + } +#endif /* !NEW_PROMPTS */ + + if (console) { + /* Try regular password check, if allowed */ + if (!strcmp(crypt(pbuf, thisuser.pw_passwd), thisuser.pw_passwd)) + goto ok; + } else { + int i = opiegetsequence(&opie); + if (!opieverify(&opie, pbuf)) { + /* OPIE authentication succeeded */ + if (i < 5) + fprintf(stderr, "Warning: Change %s's OTP secret pass phrase NOW!\n", user); + else + if (i < 10) + fprintf(stderr, "Warning: Change %s's OTP secret pass phrase soon.\n", user); + goto ok; + }; + }; +error: + opieverify(&opie, ""); + fprintf(stderr, "Sorry\n"); + syslog(LOG_CRIT, "'%s' failed for %s on %s", argv[0], Getlogin(), ttyname(2)); +#if HAVE_SULOG + sulog(0, NULL); +#endif /* HAVE_SULOG */ + exit(2); + +ok: + syslog(LOG_NOTICE, "'%s' by %s on %s", argv[0], Getlogin(), ttyname(2)); +#if HAVE_SULOG + sulog(1, NULL); +#endif /* HAVE_SULOG */ + + if (setgid(thisuser.pw_gid) < 0) { + perror("su: setgid"); + exit(3); + } + if (initgroups(user, thisuser.pw_gid)) { + fprintf(stderr, "su: initgroups failed (errno=%d)\n", errno); + exit(4); + } + if (setuid(thisuser.pw_uid) < 0) { + perror("su: setuid"); + exit(5); + } + if (thisuser.pw_shell && *thisuser.pw_shell) + shell = thisuser.pw_shell; + if (fulllogin) { + if (p = getenv("TERM")) { + strncpy(termbuf, p, sizeof(termbuf)); + cleanenv[4] = termbuf; + } + environ = cleanenv; + } + if (fulllogin || strcmp(user, "root") != 0) + lsetenv("USER", thisuser.pw_name, userbuf); + lsetenv("SHELL", shell, shellbuf); + lsetenv("HOME", thisuser.pw_dir, homebuf); + +#if HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H + setpriority(PRIO_PROCESS, 0, 0); +#endif /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */ + + if (fastlogin) { + *argv-- = "-f"; + *argv = "su"; + } else + if (fulllogin) { + if (chdir(thisuser.pw_dir) < 0) { + fprintf(stderr, "No directory\n"); + exit(6); + } + *argv = "-su"; + } else { + *argv = "su"; + } + + catchexit(); + +#if DEBUG + syslog(LOG_DEBUG, "execing %s", shell); +#endif /* DEBUG */ + execv(shell, argv); + fprintf(stderr, "No shell\n"); + exit(7); +} diff --git a/contrib/opie/opietest.c b/contrib/opie/opietest.c new file mode 100644 index 0000000..edccf74 --- /dev/null +++ b/contrib/opie/opietest.c @@ -0,0 +1,255 @@ +/* opietest.c: Quick, though definitely not complete, regression test for + libopie. This is intended to catch two things: + + (1) when changes break something + (2) if some system wierdness (libc, compiler, or CPU/hardware) is + not getting along at all with OPIE. + + It's safe to say that, if tests fail, OPIE isn't going to work right +on your system. The converse is not such a safe statement. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Modified by cmetz for OPIE 2.3. Use new calling conventions for + opiebtoa8()/atob8(). opiegenerator() outputs hex now. + Modified by cmetz for OPIE 2.22. Test opielock()/opieunlock() + refcount support. + Created by cmetz for OPIE 2.2. +*/ +#include "opie_cfg.h" +#include +#include "opie.h" + +char buffer[1024]; +int tests_passed = 0; +int tests_failed = 0; +int ntests = 0, testn = 0; + +int testatob8() +{ + static char testin[] = "0123456789abcdef"; + static unsigned char testout[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + + if (!opieatob8(buffer, testin)) + return -1; + + if (memcmp(buffer, testout, sizeof(testout))) + return -1; + + return 0; +} + +int testbtoa8() +{ + static unsigned char testin[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + static char testout[] = "0123456789abcdef"; + + if (!opiebtoa8(buffer, testin)) + return -1; + + if (memcmp(buffer, testout, sizeof(testout))) + return -1; + + return 0; +} + +int testbtoe() +{ + static unsigned char testin[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + static char testout[] = "AIM HEW BLUM FED MITE WARM"; + + if (!opiebtoe(buffer, testin)) + return -1; + + if (memcmp(buffer, testout, sizeof(testout))) + return -1; + + return 0; +} + +int testetob() +{ + static char testin[] = "AIM HEW BLUM FED MITE WARM"; + static unsigned char testout[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + + if (opieetob(buffer, testin) != 1) + return -1; + + if (memcmp(buffer, testout, sizeof(testout))) + return -1; + + return 0; +} + +int testgenerator() +{ + static char testin1[] = "otp-md5 123 ke1234"; + static char testin2[] = "this is a test"; + /* static char testout[] = "END KERN BALM NICK EROS WAVY"; */ + static char testout[] = "11D4 C147 E227 C1F1"; + + if (opiegenerator(testin1, testin2, buffer)) + return -1; + + if (memcmp(buffer, testout, sizeof(testout))) + return -1; + + return 0; +} + +int testgetsequence() +{ + struct opie testin; + testin.opie_n = 42; + + if (opiegetsequence(&testin) != 42) + return -1; + + return 0; +} + +int testhashmd4() +{ + static unsigned char testin[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + static unsigned char testout[] = { 0x9f, 0x40, 0xfb, 0x84, 0xb, 0xf8, 0x7f, 0x4b }; + + opiehash(testin, 4); + + if (memcmp(testin, testout, sizeof(testout))) + return -1; + + return 0; +} + +int testhashmd5() +{ + static unsigned char testin[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + static unsigned char testout[] = { 0x78, 0xdd, 0x1a, 0x37, 0xf8, 0x91, 0x54, 0xe1 }; + + opiehash(testin, 5); + + if (memcmp(testin, testout, sizeof(testout))) + return -1; + + return 0; +} + +int testkeycrunch() +{ + static char testin1[] = "ke1234"; + static char testin2[] = "this is a test"; + static unsigned char testout[] = { 0x2e, 0xd3, 0x5d, 0x74, 0x3e, 0xa9, 0xe9, 0xe8 }; + + if (opiekeycrunch(5, buffer, testin1, testin2)) + return -1; + + if (memcmp(buffer, testout, sizeof(testout))) + return -1; + + return 0; +} + +int testlock() +{ + int i; + + for (i = 0; i < 3; i++) + if (opielock("__opietest")) + return -1; + + return 0; +} + +int testpasscheck() +{ + static char testin1[] = "abadone"; + static char testin2[] = "A more reasonable choice."; + + if (!opiepasscheck(testin1)) + return -1; + + if (opiepasscheck(testin2)) + return -1; + + return 0; +} + +int testunlock() +{ + int i; + + for (i = 0; i < 3; i++) + if (opieunlock()) + return -1; + + if (opieunlock() != -1) + return -1; + + return 0; +} + +struct opietest { + int (*f)(); + char *n; +}; + +static struct opietest opietests[] = { + { testatob8, "atob8" }, + { testbtoa8, "btoa8" }, + { testbtoe, "btoe" }, + { testetob, "etob" }, +/* { testchallenge, "challenge" }, */ + { testgenerator, "generator" }, + { testgetsequence, "getsequence" }, +/* { testgetutmpentry, "getutmpentry" }, */ + { testhashmd4, "hash(MD4)" }, + { testhashmd5, "hash(MD5)" }, +/* { testinsecure, "insecure" }, */ + { testkeycrunch, "keycrunch" }, + { testlock, "lock" }, +/* { testpututmpentry, "pututmpentry" }, */ +/* { testrandomchallenge, "randomchallenge" }, */ +/* { testreadpass, "readpass" }, */ + { testunlock, "unlock" }, +/* { testverify, "verify" }, */ +/* { testversion, "version" }, */ + { NULL, NULL } +}; + +int main FUNCTION((argc, argv), int argc AND char *argv[]) +{ + struct opietest *opietest; + + for (opietest = opietests; opietest->n; opietest++) + ntests++; + + printf("opietest: executing %d tests\n", ntests); + + for (opietest = opietests, testn = 1; opietest->n; opietest++) { + printf("(%2d/%2d) testing opie%s... ", testn++, ntests, opietest->n); + if (opietest->f()) { + printf("FAILED!\n"); + tests_failed++; + } else { + printf("passed\n"); + tests_passed++; + opietest->f = NULL; + } + } + + printf("opietest: completed %d tests. %d tests passed, %d tests failed.\n", ntests, tests_passed, tests_failed); + if (tests_failed) { + printf("opietest: please correct the following failures before attempting to use OPIE:\n"); + for (opietest = opietests; opietest->n; opietest++) + if (opietest->f) + printf(" opie%s\n", opietest->n); + exit(1); + } + exit(0); +} diff --git a/contrib/opie/options.h b/contrib/opie/options.h new file mode 100644 index 0000000..05f1e55 --- /dev/null +++ b/contrib/opie/options.h @@ -0,0 +1,85 @@ +/* options.h: Configuration options the end user might want to tweak. + +%%% copyright-cmetz +This software is Copyright 1996 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + + History: + + Created by cmetz for OPIE 2.3 using the old Makefile.source as a + guide. +*/ +/* + Which hash should the OPIE server software use? + + We strongly recommend that you use MD5. MD4 is faster, but less secure. +If you are migrating from Bellcore S/Key version 1 and wish to use the +existing key database, you must use MD4. In this case, you should consider +ways to re-key your users using MD5. +*/ + +#define MDX 5 /* Use MD5 */ +/* #define MDX 4 /* Use MD4 */ + +/* + Ask users to re-type their secret pass phrases? + + Doing so helps catch typing mistakes, but some users find it annoying. +*/ + +/* #define RETYPE 1 /* Ask users to re-type their secret pass phrases */ +#define RETYPE 0 /* Don't ask users to re-type their secret pass phrases */ + +/* + Generater lock files to serialize OTP logins? + + There is a potential race attack on OTP when more than one session can +respond to the same challenge at the same time. This locking only allows +one session at a time per principal (user) to attempt to log in using OTP. +The locking, however, creates a denial-of-service attack as a trade-off and +can be annoying if you have a legitimate need for two sessions to attempt +to authenticate as the same principal at the same time. +*/ + +#define USER_LOCKING 1 /* Serialize OTP challenges for a principal */ +/* #define USER_LOCKING 0 /* Don't serialize OTP challenges */ + +/* + Should su(8) refuse to switch to disabled accounts? + + Traditionally, su(8) can switch to any account, even if it is disabled. +In most systems, there is no legitimate need for this capability and it can +create security problems. +*/ + +#define SU_STAR_CHECK 1 /* Refuse to switch to disabled accounts */ +/* #define SU_STAR_CHECK 0 /* Allow switching to disabled accounts */ + +/* + Should OPIE use more informative prompts? + + The new-style, more informative prompts better indicate to the user what +is being asked for. However, some automated login scripts depend on the +wording of some prompts and will fail if you change them. +*/ + +#define NEW_PROMPTS 1 /* Use the more informative prompts */ +/* #define NEW_PROMPTS 0 /* Use the more compatible prompts */ + +/* + Should the user be allowed to override "insecure" terminal checks? + + The "insecure" terminal checks are designed to help make it more clear +to users that they shouldn't disclose their secret over insecure lines +by refusing to accept the secret directly. These checks aren't perfect and +sometimes will cause OPIE to refuse to work when it really should. Allowing +users to override the terminal checks also helps the process of creating +OTP sequences for users. However, allowing users to override the terminal +checks also allows users to shoot themselves in the foot, which isn't usually +what you want. +*/ + +#define INSECURE_OVERRIDE 0 /* Don't allow users to override the checks */ +/* #define INSECURE_OVERRIDE 1 /* Allow users to override the checks */ diff --git a/contrib/opie/permsfile.c b/contrib/opie/permsfile.c new file mode 100644 index 0000000..10b98c5 --- /dev/null +++ b/contrib/opie/permsfile.c @@ -0,0 +1,163 @@ +/* permsfile.c: implement SunOS /etc/fbtab and Solaris /etc/logindevperm + functionality to set device permissions on login + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.3. Check for NULL return from + ftpglob(), combine some expressions, fix a typo. Made file + selection a bit more generic. + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Add opie.h. Ifdef around a header. + Written at NRL for OPIE 2.0. +*/ + +#include "opie_cfg.h" +#ifdef HAVE_LOGIN_PERMFILE +#include +#include +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ +#include +#include "opie.h" + +/* Line buffer size (one more than max line length) */ +#define BUFSIZE 128 +/* Maximum number of list items in a field */ +#define LISTSIZE 10 + +static char buf[BUFSIZE], buf2[8]; + +char **ftpglob __P((char *)); + +VOIDRET opiefatal FUNCTION((x), char *x) +{ + fprintf(stderr, x); + exit(1); +} + +#include "glob.c" + +static int getalist FUNCTION((string, list), char **string AND char **list) +{ + char *s = *string; + int i = 0; + + while (*s && (*s != '\n') && (*s != ' ') && (*s != '\t')) + if ((*s == ':') || (*s == ',')) { + *(s++) = 0; + list[i++] = *string; + *string = s; + if (i == LISTSIZE) + return i; + } else + s++; + + if ((int) (s) - (int) (*string)) { + *s = 0; + list[i++] = *string; + } + *string = ++s; + + return i; +} + +static VOIDRET doaline FUNCTION((line, name, ttyn, uid, gid), char *line AND char *name AND char *ttyn AND uid_t uid AND gid_t gid) +{ + char *ptr; + int i; + int applies, llen; + char *listbuf[LISTSIZE], **globlist; + + if (ptr = strchr(buf, '#')) + *ptr = 0; + + /* Skip whitespace */ + for (ptr = buf; *ptr && ((*ptr == ' ') || (*ptr == '\t')); + ptr++); + + if (!*ptr) + return; + + /* (Optional) Field 1: user name(s) */ + if ((*ptr != '/') && (*ptr != '~')) { + llen = getalist(&ptr, listbuf); + for (applies = i = 0; (i < llen) && !applies; i++) + if (!strcmp(listbuf[i], name)) + applies++; + while (*ptr && ((*ptr == ' ') || (*ptr == '\t'))) + ptr++; + if (!applies || !*ptr) + return; + } + /* Field 2: terminal(s) */ + llen = getalist(&ptr, listbuf); + for (applies = i = 0; (i < llen) && !applies; i++) + if (!strcmp(listbuf[i], ttyn)) + applies++; + + while (*ptr && ((*ptr == ' ') || (*ptr == '\t'))) + ptr++; + + if (!applies || !*ptr) + return; + + /* Field 3: mode */ + for (applies = 0; *ptr && (*ptr >= '0') && (*ptr <= '7'); + applies = (applies << 3) | (*(ptr++) - '0')); + + while (*ptr && ((*ptr == ' ') || (*ptr == '\t'))) + ptr++; + + if (!*ptr) + return; + + /* Field 4: devices (the fun part...) */ + llen = getalist(&ptr, listbuf); + for (i = 0; i < llen; i++) { + if (globlist = ftpglob(listbuf[i])) + while (*globlist) { +#ifdef DEBUG + syslog(LOG_DEBUG, "setting %s to %d/%d %o", *globlist, uid, gid, applies); +#endif /* DEBUG */ + if ((chown(*globlist, uid, gid) < 0) && (errno != ENOENT)) + perror("chown"); + if ((chmod(*(globlist++), applies) < 0) && (errno != ENOENT)) + perror("chmod"); + } + } +} + +VOIDRET permsfile FUNCTION((name, ttyn, uid, gid), char *name AND char *ttyn AND uid_t uid AND gid_t gid) +{ + FILE *fh; + + if (!(fh = fopen(HAVE_LOGIN_PERMFILE, "r"))) { + syslog(LOG_ERR, "Can't open %s!", HAVE_LOGIN_PERMFILE); + fprintf(stderr, "Warning: Can't set device permissions.\n"); + return; + } + do { + if (feof(fh)) + return; + if (fgets(buf, BUFSIZE, fh) == NULL) + return; + buf[BUFSIZE] = 0; + + doaline(buf, name, ttyn, uid, gid); + } + while (1); +} +#endif /* HAVE_LOGIN_PERMFILE */ diff --git a/contrib/opie/popen.c b/contrib/opie/popen.c new file mode 100644 index 0000000..22477a6 --- /dev/null +++ b/contrib/opie/popen.c @@ -0,0 +1,204 @@ +/* popen.c: A "safe" pipe open routine. + +%%% portions-copyright-cmetz +Portions of this software are Copyright 1996 by Craig Metz, All Rights +Reserved. The Inner Net License Version 2 applies to these portions of +the software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +Portions of this software are Copyright 1995 by Randall Atkinson and Dan +McDonald, All Rights Reserved. All Rights under this copyright are assigned +to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and +License Agreement applies to this software. + + History: + + Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. + Removed useless string. ifdef around some headers. + Modified at NRL for OPIE 2.1. Optimized for only one pipe at a time. + Added minimal version of sigprocmask(). Moved some pid_t + dancing to the config headers. + Modified at NRL for OPIE 2.0. + Originally from BSD. + +*/ +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software written by Ken Arnold and + * published in UNIX Review, Vol. 6, No. 8. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "opie_cfg.h" + +#include +#include +#if HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ +#if HAVE_SYS_SIGNAL_H +#include +#endif /* HAVE_SYS_SIGNAL_H */ +#if HAVE_UNISTD_H +#include +#endif /* HAVE_UNISTD_H */ +#include +#if HAVE_STDLIB_H +#include +#endif /* HAVE_STDLIB_H */ +#if HAVE_STRING_H +#include +#endif /* HAVE_STRING_H */ + +#include "opie.h" + +char **ftpglob __P((register char *)); +char **copyblk __P((char **)); +VOIDRET blkfree __P((char **)); + +/* + * Special version of popen which avoids call to shell. This insures noone + * may create a pipe to a hidden program as a side effect of a list or dir + * command. + */ +static pid_t child_pid = -1; +static int pipe_fd; + +FILE *ftpd_popen FUNCTION((program, type), char *program AND char *type) +{ + register char *cp; + FILE *iop; + int argc, gargc, pdes[2]; + char **pop, *argv[100], *gargv[1000], *vv[2]; + + if ((*type != 'r' && *type != 'w') || type[1]) + return (NULL); + + if (pipe(pdes) < 0) + return (NULL); + + /* break up string into pieces */ + for (argc = 0, cp = program;; cp = NULL) + if (!(argv[argc++] = strtok(cp, " \t\n"))) + break; + + /* glob each piece */ + gargv[0] = argv[0]; + for (gargc = argc = 1; argv[argc]; argc++) { + if (!(pop = (char **) ftpglob(argv[argc]))) { + /* globbing failed */ + vv[0] = argv[argc]; + vv[1] = NULL; + pop = (char **) copyblk(vv); + } + argv[argc] = (char *) pop; /* save to free later */ + while (*pop && gargc < 1000) + gargv[gargc++] = *pop++; + } + gargv[gargc] = NULL; + + iop = NULL; + switch (child_pid = fork()) { + case -1: /* error */ + close(pdes[0]); + close(pdes[1]); + goto pfree; + /* NOTREACHED */ + case 0: /* child */ + if (*type == 'r') { + if (pdes[1] != 1) { + dup2(pdes[1], 1); + dup2(pdes[1], 2); /* stderr, too! */ + close(pdes[1]); + } + close(pdes[0]); + } else { + if (pdes[0] != 0) { + dup2(pdes[0], 0); + close(pdes[0]); + } + close(pdes[1]); + } + execv(gargv[0], gargv); + _exit(1); + } + + /* parent; assume fdopen can't fail... */ + if (*type == 'r') { + iop = fdopen(pipe_fd = pdes[0], type); + close(pdes[1]); + } else { + iop = fdopen(pipe_fd = pdes[1], type); + close(pdes[0]); + } + +pfree: for (argc = 1; argv[argc] != NULL; argc++) { + blkfree((char **) argv[argc]); + free((char *) argv[argc]); + } + return (iop); +} + +int ftpd_pclose FUNCTION((iop), FILE *iop) +{ + int status; + pid_t pid; + sigset_t omask, mask; + + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGQUIT); + sigaddset(&mask, SIGHUP); + + /* pclose returns -1 if stream is not associated with a `popened' command, + or, if already `pclosed'. */ + if ((child_pid < 0) || (fileno(iop) != pipe_fd)) + return (-1); + + fclose(iop); + sigprocmask(SIG_BLOCK, &mask, &omask); + + while ((pid = wait(&status)) != child_pid && (pid != -1)); + sigprocmask(SIG_SETMASK, &omask, NULL); + + child_pid = -1; + pipe_fd = -1; + +#ifdef WEXITSTATUS + /* this is the fully POSIX compliant implementation */ + return (pid == -1 ? -1 : WEXITSTATUS(status)); +#else + return (pid == -1 ? -1 : status.w_status); +#endif +} -- cgit v1.1