Initial import of OPIE v2.3 from

ftp://ftp.nrl.navy.mil/pub/security/opie/
This commit is contained in:
Paul Traina 1997-02-06 17:52:29 +00:00
commit 3c491303b5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/opie/dist/; revision=22347
svn path=/vendor/opie/2.3/; revision=22349; tag=vendor/opie/2.3
94 changed files with 22497 additions and 0 deletions

81
contrib/opie/BUG-REPORT Normal file
View file

@ -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
<opie-bugs@inner.net>. 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
<opie-bugs@inner.net>. 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 <license@inner.net>.

View file

@ -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).
----------------------------------------------------------------------

88
contrib/opie/INSTALL Normal file
View file

@ -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 <license@inner.net>.
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.

45
contrib/opie/License.TIN Normal file
View file

@ -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 <name(s)>, 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.

271
contrib/opie/Makefile.in Normal file
View file

@ -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 <license@inner.net>.
#
# 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

391
contrib/opie/README Normal file
View file

@ -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 <license@inner.net>.
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.

118
contrib/opie/acconfig.h Normal file
View file

@ -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 <license@inner.net>.
/* 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

324
contrib/opie/config.h.in Normal file
View file

@ -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 <alloca.h> and it should be used (not on Ultrix). */
#undef HAVE_ALLOCA_H
/* Define if you have <sys/wait.h> 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 <crypt.h> header file. */
#undef HAVE_CRYPT_H
/* Define if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define if you have the <lastlog.h> header file. */
#undef HAVE_LASTLOG_H
/* Define if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define if you have the <ndir.h> header file. */
#undef HAVE_NDIR_H
/* Define if you have the <paths.h> header file. */
#undef HAVE_PATHS_H
/* Define if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define if you have the <shadow.h> header file. */
#undef HAVE_SHADOW_H
/* Define if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
/* Define if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define if you have the <sys/dir.h> header file. */
#undef HAVE_SYS_DIR_H
/* Define if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
/* Define if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define if you have the <sys/ndir.h> header file. */
#undef HAVE_SYS_NDIR_H
/* Define if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define if you have the <sys/signal.h> header file. */
#undef HAVE_SYS_SIGNAL_H
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define if you have the <sys/utsname.h> header file. */
#undef HAVE_SYS_UTSNAME_H
/* Define if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* Define if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if you have the <utmpx.h> 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

View file

@ -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

4089
contrib/opie/configure vendored Executable file

File diff suppressed because it is too large Load diff

455
contrib/opie/configure.in Normal file
View file

@ -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 <license@inner.net>.
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 <stdarg.h>
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 <stdio.h>
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 <sys/types.h>
#include <utmp.h>], [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 <sys/types.h>
#include <utmp.h>], [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 <sys/types.h>
#include <utmp.h>], [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 <sys/types.h>
dnl #include <utmp.h>], [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 <sys/time.h>
#endif /* HAVE_SYS_TIME_H */
#if HAVE_UNISTD_H
#include <unistd.h>
#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 <sys/time.h>
#endif /* HAVE_SYS_TIME_H */
#if HAVE_UNISTD_H
#include <unistd.h>
#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

View file

@ -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?"

1286
contrib/opie/ftpcmd.y Normal file

File diff suppressed because it is too large Load diff

667
contrib/opie/glob.c Normal file
View file

@ -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 <license@inner.net>.
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 <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
#include <sys/stat.h>
#include <dirent.h>
#if HAVE_PWD_H
#include <pwd.h>
#endif /* HAVE_PWD_H */
#include <errno.h>
#include <stdio.h>
#include <string.h>
#if HAVE_LIMITS_H
#include <limits.h>
#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));
}

238
contrib/opie/install-sh Normal file
View file

@ -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

View file

@ -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 <license@inner.net>.
#
# 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

View file

@ -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 <jot@cray.com> 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 <config.h>
#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 <stdio.h>
#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 */

View file

@ -0,0 +1 @@
int _bogus;

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.3.
*/
#include "opie_cfg.h"
#include "opie.h"
void endutent FUNCTION_NOARGS
{
}

View file

@ -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 <license@inner.net>.
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 <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_STDLIB_H
#include <stdlib.h>
#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 */

View file

@ -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 <license@inner.net>.
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 */
}

View file

@ -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 <license@inner.net>.
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 <stdio.h>
#if HAVE_STRING_H
#include <string.h>
#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;
}

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.3.
*/
#include "opie_cfg.h"
#include <stdio.h>
#include <utmp.h>
#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;
}

View file

@ -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 <license@inner.net>.
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 <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
#include <stdio.h>
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING */
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <grp.h>
#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);
}

View file

@ -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 <license@inner.net>.
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;
}

View file

@ -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 <license@inner.net>.
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;
}

View file

@ -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 <license@inner.net>.
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;
}

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.3.
*/
#include "opie_cfg.h"
#include <stdio.h>
#include <utmp.h>
#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);
}

View file

@ -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 <license@inner.net>.
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;
}

View file

@ -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 <license@inner.net>.
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;
}

View file

@ -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 <license@inner.net>.
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 <sys/types.h>
#if HAVE_SIGNAL_H
#include <signal.h>
#endif /* HAVE_SIGNAL_H */
#if HAVE_SYS_SIGNAL_H
#include <sys/signal.h>
#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;
}
}

View file

@ -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 <license@inner.net>.
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 */
}

View file

@ -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 <license@inner.net>.
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 */
}

View file

@ -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 <license@inner.net>.
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;
}

View file

@ -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 <license@inner.net>.
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 */
}

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.3.
*/
#include "opie_cfg.h"
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#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;
}

View file

@ -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 <license@inner.net>.
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 <sys/param.h>
#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 */
}

View file

@ -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

View file

@ -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 <license@inner.net>.
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 <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_STDLIB_H
#include <stdlib.h>
#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);
}

View file

@ -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 <license@inner.net>.
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 <stdio.h>
#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;
}

View file

@ -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 <license@inner.net>.
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;
}

2266
contrib/opie/libopie/btoe.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -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 <license@inner.net>.
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;
}

View file

@ -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 <license@inner.net>.
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 <stdio.h>
#include <string.h>
#if DEBUG
#include <syslog.h>
#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;
}

View file

@ -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 <license@inner.net>.
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 <string.h>
#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;
}

View file

@ -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 <license@inner.net>.
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;
}

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.3 (re-write).
*/
#include "opie_cfg.h"
#include <stdio.h>
#include <sys/types.h>
#include <utmp.h>
#if DOUTMPX
#include <utmpx.h>
#define getutline(x) getutxline(x)
#define utmp utmpx
#endif /* DOUTMPX */
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#if DEBUG
#include <syslog.h>
#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;
}

View file

@ -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 <license@inner.net>.
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;
}
}

View file

@ -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 <license@inner.net>.
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;
}
}

View file

@ -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 <license@inner.net>.
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 <stdio.h>
#include <string.h>
#include <stdlib.h> /* ANSI C standard library */
#include <sys/param.h>
#include <unistd.h>
#include <utmp.h>
#if DOUTMPX
#include <utmpx.h>
#define utmp utmpx
#endif /* DOUTMPX */
#if HAVE_SYS_UTSNAME_H
#include <sys/utsname.h>
#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 */
}

View file

@ -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 <license@inner.net>.
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 <string.h>
#endif /* HAVE_STRING_H */
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif /* HAVE_STDLIB_H */
#include <ctype.h>
#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;
}

175
contrib/opie/libopie/lock.c Normal file
View file

@ -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 <license@inner.net>.
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 <string.h>
#endif /* HAVE_STRING_H */
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <fcntl.h>
#if HAVE_STDLIB_H
#include <stdlib.h>
#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 */
}

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.3.
*/
#include "opie_cfg.h"
#include <stdio.h>
#include <sys/types.h>
#include <utmp.h>
#if DOUTMPX
#include <utmpx.h>
#define pututline(x) pututxline(x)
#define utmp utmpx
#endif /* DOUTMPX */
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#include <sys/stat.h>
#if DEBUG
#include <syslog.h>
#include <errno.h>
#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;
}

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.3 (re-write).
*/
#include "opie_cfg.h"
#include <stdio.h>
#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;
}

267
contrib/opie/libopie/md4c.c Normal file
View file

@ -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 <license@inner.net>.
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);
}

304
contrib/opie/libopie/md5c.c Normal file
View file

@ -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 <license@inner.net>.
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));
}

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.22.
*/
#include "opie_cfg.h"
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#include <ctype.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_SYS_UTSNAME_H
#include <sys/utsname.h>
#endif /* HAVE_SYS_UTSNAME_H */
#include <errno.h>
#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;
}
}
}

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.3.
*/
#include "opie_cfg.h"
#include <stdio.h>
#include <sys/types.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <sys/stat.h>
#include <errno.h>
#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;
}

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.3 using generator.c as a guide.
*/
#include "opie_cfg.h"
#if HAVE_STRING_H
#include <string.h>
#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;
}

View file

@ -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 <license@inner.net>.
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 <stdio.h>
#include <string.h>
#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;
}

View file

@ -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 <license@inner.net>.
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;
}

View file

@ -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 <license@inner.net>.
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);
}

View file

@ -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 <license@inner.net>.
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 <stdio.h>
#include <string.h>
#include <stdlib.h> /* ANSI C standard library */
#ifdef unix
#include <fcntl.h> /* POSIX file control function headers */
#include <termios.h> /* POSIX Terminal I/O functions */
#if HAVE_UNISTD_H
#include <unistd.h> /* POSIX standard definitions */
#endif /* HAVE_UNISTD_H */
#include <signal.h>
#include <setjmp.h>
#endif /* unix */
#ifdef __MSDOS__
#include <dos.h>
#endif /* __MSDOS__ */
#ifdef __OS2__
#define INCL_KBD
#include <os2.h>
#include <io.h>
#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;
}

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.3.
*/
#include "opie_cfg.h"
#include <stdio.h>
#include <sys/types.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif /* HAVE_STDLIB_H */
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#include <ctype.h>
#include <errno.h>
#if DEBUG
#include <syslog.h>
#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;
}

View file

@ -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 <license@inner.net>.
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 <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <fcntl.h>
#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 */
}

View file

@ -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 <license@inner.net>.
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 <string.h>
#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;
}

View file

@ -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 <license@inner.net>.
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);
}

View file

@ -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 <license@inner.net>.
History:
Created by cmetz for OPIE 2.3 from passwd.c.
*/
#include "opie_cfg.h"
#include <stdio.h>
#if TM_IN_SYS_TIME
#include <sys/time.h>
#else /* TM_IN_SYS_TIME */
#include <time.h>
#endif /* TM_IN_SYS_TIME */
#include <sys/types.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#if HAVE_STDLIB_H
#include <stdlib.h>
#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;
}

154
contrib/opie/logwtmp.c Normal file
View file

@ -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 <license@inner.net>.
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 <sys/types.h>
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif /* HAVE_SYS_TIME_H */
#include <sys/stat.h>
#include <fcntl.h>
#include <utmp.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#include "opie.h"
static int fd = -1;
#if DOUTMPX
static int fdx = -1;
#include <utmpx.h>
#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 */
}

346
contrib/opie/opie.4 Normal file
View file

@ -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 <license@inner.net>.
.\"
.\" 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 <stdio.h> somewhere. Then, below the other
includes such as <stdio.h>, 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 <stdio.h>
.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

224
contrib/opie/opie.h Normal file
View file

@ -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 <license@inner.net>.
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 */

167
contrib/opie/opie_cfg.h Normal file
View file

@ -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 <license@inner.net>.
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 <dirent.h>
#else /* HAVE_DIRENT_H */
#define dirent direct
#if HAVE_SYS_NDIR_H
#include <sys/ndir.h>
#endif /* HAVE_SYS_NDIR_H */
#if HAVE_SYS_DIR_H
#include <sys/dir.h>
#endif /* HAVE_SYS_DIR_H */
#if HAVE_NDIR_H
#include <ndir.h>
#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

87
contrib/opie/opieaccess.5 Normal file
View file

@ -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

280
contrib/opie/opieftpd.8 Normal file
View file

@ -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

1643
contrib/opie/opieftpd.c Normal file

File diff suppressed because it is too large Load diff

88
contrib/opie/opiegen.1 Normal file
View file

@ -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 <license@inner.net>.
.\"
.\" 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

88
contrib/opie/opiegen.c Normal file
View file

@ -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 <license@inner.net>.
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 <stdio.h>
#if DEBUG
#include <syslog.h>
#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;
}

99
contrib/opie/opieinfo.1 Normal file
View file

@ -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 <license@inner.net>.
.\"
.\" 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 <user_name>
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

90
contrib/opie/opieinfo.c Normal file
View file

@ -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 <license@inner.net>.
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 <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_PWD_H
#include <pwd.h>
#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;
}

173
contrib/opie/opiekey.1 Normal file
View file

@ -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 <license@inner.net>.
.\"
.\" 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 <count>
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 <type>
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

375
contrib/opie/opiekey.c Normal file
View file

@ -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 <license@inner.net>.
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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "opie.h"
#ifdef __MSDOS__
#include <dos.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#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;
}

66
contrib/opie/opiekeys.5 Normal file
View file

@ -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

131
contrib/opie/opielogin.1 Normal file
View file

@ -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 <license@inner.net>.
.\"
.\" 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

1428
contrib/opie/opielogin.c Normal file

File diff suppressed because it is too large Load diff

176
contrib/opie/opiepasswd.1 Normal file
View file

@ -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 <license@inner.net>.
.\"
.\" 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

429
contrib/opie/opiepasswd.c Normal file
View file

@ -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 <license@inner.net>.
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 <pwd.h>
#endif /* HAVE_PWD_H */
#include <stdio.h>
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#include <stdio.h>
#include <sys/types.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_STDLIB_H
#include <stdlib.h>
#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);
}
}
}
}
}

82
contrib/opie/opieserv.1 Normal file
View file

@ -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 <license@inner.net>.
.\"
.\" 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

83
contrib/opie/opieserv.c Normal file
View file

@ -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 <license@inner.net>.
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 <stdio.h>
#if DEBUG
#include <syslog.h>
#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);
}
}

101
contrib/opie/opiesu.1 Normal file
View file

@ -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 <license@inner.net>.
.\"
.\" 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

448
contrib/opie/opiesu.c Normal file
View file

@ -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 <license@inner.net>.
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 <stdio.h>
#if HAVE_PWD_H
#include <pwd.h>
#endif /* HAVE_PWD_H */
#include <grp.h>
#include <syslog.h>
#include <sys/types.h>
#if HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else /* TIME_WITH_SYS_TIME */
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else /* HAVE_SYS_TIME_H */
#include <time.h>
#endif /* HAVE_SYS_TIME_H */
#endif /* TIME_WITH_SYS_TIME */
#include <sys/resource.h>
#else /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */
#if TM_IN_SYS_TIME
#include <sys/time.h>
#else /* TM_IN_SYS_TIME */
#include <time.h>
#endif /* TM_IN_SYS_TIME */
#endif /* HAVE_SETPRIORITY && HAVE_SYS_RESOURCE_H */
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif /* HAVE_STDLIB_H */
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#include <errno.h>
#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 <shadow.h>
#endif /* HAVE_SHADOW_H */
#if HAVE_CRYPT_H
#include <crypt.h>
#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);
}

255
contrib/opie/opietest.c Normal file
View file

@ -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 <license@inner.net>.
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 <stdio.h>
#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);
}

85
contrib/opie/options.h Normal file
View file

@ -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 <license@inner.net>.
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 */

163
contrib/opie/permsfile.c Normal file
View file

@ -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 <license@inner.net>.
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 <stdio.h>
#include <sys/types.h>
#if HAVE_STRING_H
#include <string.h>
#endif /* HAVE_STRING_H */
#include <syslog.h>
#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 */

204
contrib/opie/popen.c Normal file
View file

@ -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 <license@inner.net>.
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 <sys/types.h>
#include <sys/wait.h>
#if HAVE_SIGNAL_H
#include <signal.h>
#endif /* HAVE_SIGNAL_H */
#if HAVE_SYS_SIGNAL_H
#include <sys/signal.h>
#endif /* HAVE_SYS_SIGNAL_H */
#if HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <stdio.h>
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif /* HAVE_STDLIB_H */
#if HAVE_STRING_H
#include <string.h>
#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
}