Import from sourceforge svn

This commit is contained in:
Meutel 2016-07-10 19:28:38 +02:00
commit a0dd02b3f5
163 changed files with 49273 additions and 0 deletions

5
CONTRIBUTORS Normal file
View File

@ -0,0 +1,5 @@
* Foremost, OpenSSH from which this project is derived.
* Jamie Beverly
* Rafael D'Halleweyn - 2011-06-05 18:56:24 EDT
* Jan-Pieter Cornet ( johnpc ) - 2012-03-23 03:25:52 PDT
* chrysn@fsfe.org

114
LICENSE.OpenSSL Normal file
View File

@ -0,0 +1,114 @@
/* ====================================================================
* Copyright (c) 1998-2001 The OpenSSL Project. 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 acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED 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 OpenSSL PROJECT OR
* ITS 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.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
Original SSLeay License
-----------------------
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* 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 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 cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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 licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/

166
Makefile.in Normal file
View File

@ -0,0 +1,166 @@
# $Id: Makefile.in,v 1.289 2008/03/13 01:41:31 djm Exp $
#
# Copyright (c) 2000 Markus Friedl. All rights reserved.
# Modifications Copyright (c) 2008-2014 Jamie Beverly. 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.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
#
# uncomment if you run a non bourne compatable shell. Ie. csh
#SHELL = @SH@
AUTORECONF=autoreconf
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
sbindir=@sbindir@
libexecdir=@libexecdir@
datadir=@datadir@
datarootdir=@datarootdir@
mandir=@mandir@
mansubdir=@mansubdir@
sysconfdir=@sysconfdir@
piddir=@piddir@
srcdir=@srcdir@
top_srcdir=@top_srcdir@
DESTDIR=
VPATH=@srcdir@
STRIP_OPT=@STRIP_OPT@
PATHS=
CC=@CC@
LD=@LD@
CFLAGS=@CFLAGS@
CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
LIBS=@LIBS@
AR=@AR@
AWK=@AWK@
RANLIB=@RANLIB@
INSTALL=@INSTALL@
PERL=@PERL@
SED=@SED@
ENT=@ENT@
LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
LDFLAGS_SHARED = @LDFLAGS_SHARED@
EXEEXT=@EXEEXT@
INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
PAM_MODULES=pam_ssh_agent_auth.so
SSHOBJS=xmalloc.o atomicio.o authfd.o bufaux.o bufbn.o buffer.o cleanup.o entropy.o fatal.o key.o log.o misc.o secure_filename.o ssh-dss.o ssh-rsa.o uuencode.o compat.o uidswap.o
PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o get_command_line.o
MANPAGES_IN = pam_ssh_agent_auth.pod
MANPAGES = pam_ssh_agent_auth.8
MANTYPE = @MANTYPE@
#CONFIGFILES=sshd_config.out ssh_config.out moduli.out
#CONFIGFILES_IN=sshd_config ssh_config moduli
all: $(MANPAGES) $(PAM_MODULES)
$(SSHOBJS): Makefile.in config.h
$(PAM_SSH_AGENT_AUTH_OBJS): Makefile.in config.h
$(PAM_MODULES): Makefile.in config.h
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
$(LIBCOMPAT): always
(cd openbsd-compat && $(MAKE))
always:
pam_ssh_agent_auth.so: $(LIBCOMPAT) $(SSHOBJS) $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o
$(LD) $(LDFLAGS_SHARED) -o $@ $(SSHOBJS) $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lopenbsd-compat pam_ssh_agent_auth.o $(LIBS) -lpam
$(MANPAGES): $(MANPAGES_IN)
pod2man --section=8 --release=v0.10.2 --name=pam_ssh_agent_auth --official --center "PAM" pam_ssh_agent_auth.pod > pam_ssh_agent_auth.8
clean: regressclean
rm -f *.o *.a $(PAM_MODULES) logintest config.cache config.log
rm -f *.out core survey
rm -f *.so
rm -f pam_ssh_agent_auth.8
(cd openbsd-compat && $(MAKE) clean)
distclean: regressclean
rm -f *.o *.a $(PAM_MODULES) logintest config.cache config.log
rm -f *.out core
rm -f Makefile config.h config.status
rm -f openbsd-compat/regress/Makefile *~
rm -rf autom4te.cache
rm -f pam_ssh_agent_auth.8
(cd openbsd-compat && $(MAKE) distclean)
if test -d pkg ; then \
rm -fr pkg ; \
fi
veryclean: distclean
rm -f configure config.h.in *.0
mrproper: veryclean
realclean: veryclean
catman-do:
@for f in $(MANPAGES_IN) ; do \
base=`echo $$f | sed 's/\..*$$//'` ; \
echo "$$f -> $$base.0" ; \
nroff -mandoc $$f | cat -v | sed -e 's/.\^H//g' \
>$$base.0 ; \
done
distprep: catman-do
$(AUTORECONF)
-rm -rf autom4te.cache
install: $(CONFIGFILES) $(MANPAGES) $(PAM_MODULES) install-files
install-files:
$(srcdir)/mkinstalldirs $(DESTDIR)$(libexecdir)
$(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)/$(mansubdir)8
$(INSTALL) -m 644 pam_ssh_agent_auth.8 $(DESTDIR)$(mandir)/$(mansubdir)8/pam_ssh_agent_auth.8
$(INSTALL) -m 755 pam_ssh_agent_auth.so $(DESTDIR)$(libexecdir)/pam_ssh_agent_auth.so
uninstallall: uninstall
-rmdir $(DESTDIR)$(mandir)/$(mansubdir)8
-rmdir $(DESTDIR)$(libexecdir)
uninstall:
-rm -f $(DESTDIR)$(libexecdir)/pam_ssh_agent_auth.so
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/$(mansubdir)8/pam_ssh_agent_auth.8
compat-tests: $(LIBCOMPAT)
(cd openbsd-compat/regress && $(MAKE))
regressclean:
if [ -f regress/Makefile ] && [ -r regress/Makefile ]; then \
(cd regress && $(MAKE) clean) \
fi

338
OPENSSH_LICENSE Normal file
View File

@ -0,0 +1,338 @@
This file is part of the OpenSSH software.
The licences which components of this software fall under are as
follows. First, we will summarize and say that all components
are under a BSD licence, or a licence more free than that.
OpenSSH contains no GPL code.
1)
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
[Tatu continues]
* However, I am not implying to give any licenses to any patents or
* copyrights held by third parties, and the software includes parts that
* are not under my direct control. As far as I know, all included
* source code is used in accordance with the relevant license agreements
* and can be used freely for any purpose (the GNU license being the most
* restrictive); see below for details.
[However, none of that term is relevant at this point in time. All of
these restrictively licenced software components which he talks about
have been removed from OpenSSH, i.e.,
- RSA is no longer included, found in the OpenSSL library
- IDEA is no longer included, its use is deprecated
- DES is now external, in the OpenSSL library
- GMP is no longer used, and instead we call BN code from OpenSSL
- Zlib is now external, in a library
- The make-ssh-known-hosts script is no longer included
- TSS has been removed
- MD5 is now external, in the OpenSSL library
- RC4 support has been replaced with ARC4 support from OpenSSL
- Blowfish is now external, in the OpenSSL library
[The licence continues]
Note that any information and cryptographic algorithms used in this
software are publicly available on the Internet and at any major
bookstore, scientific library, and patent office worldwide. More
information can be found e.g. at "http://www.cs.hut.fi/crypto".
The legal status of this program is some combination of all these
permissions and restrictions. Use only at your own responsibility.
You will be responsible for any legal consequences yourself; I am not
making any claims whether possessing or using this is legal or not in
your country, and I am not taking any responsibility on your behalf.
NO WARRANTY
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
2)
The 32-bit CRC compensation attack detector in deattack.c was
contributed by CORE SDI S.A. under a BSD-style license.
* Cryptographic attack detector for ssh - source code
*
* Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
*
* All rights reserved. Redistribution and use in source and binary
* forms, with or without modification, are permitted provided that
* this copyright notice is retained.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
* CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
* SOFTWARE.
*
* Ariel Futoransky <futo@core-sdi.com>
* <http://www.core-sdi.com>
3)
ssh-keyscan was contributed by David Mazieres under a BSD-style
license.
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
*
* Modification and redistribution in source and binary forms is
* permitted provided that due credit is given to the author and the
* OpenBSD project by leaving this copyright notice intact.
4)
The Rijndael implementation by Vincent Rijmen, Antoon Bosselaers
and Paulo Barreto is in the public domain and distributed
with the following license:
* @version 3.0 (December 2000)
*
* Optimised ANSI C code for the Rijndael cipher (now AES)
*
* @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
* @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
* @author Paulo Barreto <paulo.barreto@terra.com.br>
*
* This code is hereby placed in the public domain.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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.
5)
One component of the ssh source code is under a 3-clause BSD license,
held by the University of California, since we pulled these parts from
original Berkeley code.
* Copyright (c) 1983, 1990, 1992, 1993, 1995
* 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. 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.
6)
Remaining components of the software are provided under a standard
2-term BSD licence with the following names as copyright holders:
Markus Friedl
Theo de Raadt
Niels Provos
Dug Song
Aaron Campbell
Damien Miller
Kevin Steves
Daniel Kouril
Wesley Griffin
Per Allansson
Nils Nordman
Simon Wilkinson
Portable OpenSSH additionally includes code from the following copyright
holders, also under the 2-term BSD license:
Ben Lindstrom
Tim Rice
Andre Lucas
Chris Adams
Corinna Vinschen
Cray Inc.
Denis Parker
Gert Doering
Jakob Schlyter
Jason Downs
Juha Yrjölä
Michael Stone
Networks Associates Technology, Inc.
Solar Designer
Todd C. Miller
Wayne Schroeder
William Jones
Darren Tucker
Sun Microsystems
The SCO Group
Daniel Walsh
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
8) Portable OpenSSH contains the following additional licenses:
a) md5crypt.c, md5crypt.h
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@login.dknet.dk> wrote this file. As long as you retain this
* notice you can do whatever you want with this stuff. If we meet
* some day, and you think this stuff is worth it, you can buy me a
* beer in return. Poul-Henning Kamp
b) snprintf replacement
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell
* (papowell@astart.com) It may be used for any purpose as long as this
* notice remains intact on all source code distributions
c) Compatibility code (openbsd-compat)
Apart from the previously mentioned licenses, various pieces of code
in the openbsd-compat/ subdirectory are licensed as follows:
Some code is licensed under a 3-term BSD license, to the following
copyright holders:
Todd C. Miller
Theo de Raadt
Damien Miller
Eric P. Allman
The Regents of the University of California
Constantin S. Svintsoff
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
Some code is licensed under an ISC-style license, to the following
copyright holders:
Internet Software Consortium.
Todd C. Miller
Reyk Floeter
Chad Mynhier
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
* FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Some code is licensed under a MIT-style license to the following
copyright holders:
Free Software Foundation, Inc.
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
* "Software"), to deal in the Software without restriction, including *
* without limitation the rights to use, copy, modify, merge, publish, *
* distribute, distribute with modifications, sublicense, and/or sell *
* copies of the Software, and to permit persons to whom the Software is *
* furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included *
* in all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
* *
* Except as contained in this notice, the name(s) of the above copyright *
* holders shall not be used in advertising or otherwise to promote the *
* sale, use or other dealings in this Software without prior written *
* authorization. *
****************************************************************************/
------
$OpenBSD: LICENCE,v 1.19 2004/08/30 09:18:08 markus Exp $

38
README Normal file
View File

@ -0,0 +1,38 @@
pam_ssh_agent_auth is a PAM module which permits PAM authentication via your
keyring in a forwarded ssh-agent.
Release 0.10.2 is stable, and has been tested on FreeBSD, Solaris 10, Solaris 11,
RHEL5, RHEL6, Debian Wheezy, Ubuntu 12.04 (LTS), Ubuntu 13.10,
and MacOS X 10.7.
This module can be used to provide authentication for anything run locally that
supports PAM. It was written specifically with the intention of permitting
authentication for sudo without password entry, and also has been proven useful
for use with su as an alternative to wheel.
It serves as middle ground between the two most common, and suboptimal
alternatives for large-scale system administration: allowing rootlogin via ssh,
or using NOPASSWD in sudoers. This module allows for ssh public-key
authentication, and it does this by leveraging an authentication mechanism you
are probably already using, ssh-agent.
There are caveats of course, ssh-agent forwarding has its own security risks
which must be carefully considered for your environment. In cases where there
are not untrustworthy intermediate servers, and you wish to retain traceability,
accountability, and required authentication for privileged command invocation,
the benefits should outweigh the risks. Release 0.10.2 can be downloaded from
SourceForge: https://sourceforge.net/project/showfiles.php?group_id=249556
If you encounter any issues with usability or security, please use the project's
SourceForge tracker:
https://sourceforge.net/tracker2/?group_id=249556&atid=1126337
Note that if you wish to use this for sudo, you will need a version of sudo that
preserves the env_keep environment during authentication; and ideally a version
incorporating my minor patch which ensures RUSER is set during PAM authentication.
sudo 1.6.8p12 does not work correctly with this PAM module, because it clears the
environment (even env_keep variables) prior to attempting PAM authentication.
sudo 1.7.2p1 or later is preferred, as it correctly sets PAM_RUSER for
authentication.

86
aclocal.m4 vendored Normal file
View File

@ -0,0 +1,86 @@
dnl $Id: aclocal.m4,v 1.6 2005/09/19 16:33:39 tim Exp $
dnl
dnl OpenSSH-specific autoconf macros
dnl
dnl OSSH_CHECK_HEADER_FOR_FIELD(field, header, symbol)
dnl Does AC_EGREP_HEADER on 'header' for the string 'field'
dnl If found, set 'symbol' to be defined. Cache the result.
dnl TODO: This is not foolproof, better to compile and read from there
AC_DEFUN(OSSH_CHECK_HEADER_FOR_FIELD, [
# look for field '$1' in header '$2'
dnl This strips characters illegal to m4 from the header filename
ossh_safe=`echo "$2" | sed 'y%./+-%__p_%'`
dnl
ossh_varname="ossh_cv_$ossh_safe""_has_"$1
AC_MSG_CHECKING(for $1 field in $2)
AC_CACHE_VAL($ossh_varname, [
AC_EGREP_HEADER($1, $2, [ dnl
eval "$ossh_varname=yes" dnl
], [ dnl
eval "$ossh_varname=no" dnl
]) dnl
])
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
AC_MSG_RESULT($ossh_result)
if test "x$ossh_result" = "xyes"; then
AC_DEFINE($3, 1, [Define if you have $1 in $2])
fi
else
AC_MSG_RESULT(no)
fi
])
dnl OSSH_PATH_ENTROPY_PROG(variablename, command):
dnl Tidiness function, sets 'undef' if not found, and does the AC_SUBST
AC_DEFUN(OSSH_PATH_ENTROPY_PROG, [
AC_PATH_PROG($1, $2)
if test -z "[$]$1" ; then
$1="undef"
fi
AC_SUBST($1)
])
dnl Check for socklen_t: historically on BSD it is an int, and in
dnl POSIX 1g it is a type of its own, but some platforms use different
dnl types for the argument to getsockopt, getpeername, etc. So we
dnl have to test to find something that will work.
AC_DEFUN([TYPE_SOCKLEN_T],
[
AC_CHECK_TYPE([socklen_t], ,[
AC_MSG_CHECKING([for socklen_t equivalent])
AC_CACHE_VAL([curl_cv_socklen_t_equiv],
[
# Systems have either "struct sockaddr *" or
# "void *" as the second argument to getpeername
curl_cv_socklen_t_equiv=
for arg2 in "struct sockaddr" void; do
for t in int size_t unsigned long "unsigned long"; do
AC_TRY_COMPILE([
#include <sys/types.h>
#include <sys/socket.h>
int getpeername (int, $arg2 *, $t *);
],[
$t len;
getpeername(0,0,&len);
],[
curl_cv_socklen_t_equiv="$t"
break
])
done
done
if test "x$curl_cv_socklen_t_equiv" = x; then
AC_MSG_ERROR([Cannot find a type to use in place of socklen_t])
fi
])
AC_MSG_RESULT($curl_cv_socklen_t_equiv)
AC_DEFINE_UNQUOTED(socklen_t, $curl_cv_socklen_t_equiv,
[type to use in place of socklen_t if not defined])],
[#include <sys/types.h>
#include <sys/socket.h>])
])

147
atomicio.c Normal file
View File

@ -0,0 +1,147 @@
/* $OpenBSD: atomicio.c,v 1.25 2007/06/25 12:02:27 dtucker Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "includes.h"
#include <sys/param.h>
#include <sys/uio.h>
#include <errno.h>
#ifdef HAVE_POLL_H
#include <poll.h>
#else
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
# endif
#endif
#include <string.h>
#include <unistd.h>
#include "atomicio.h"
/*
* ensure all of data on socket comes through. f==read || f==vwrite
*/
size_t
pamsshagentauth_atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
{
char *s = _s;
size_t pos = 0;
ssize_t res;
struct pollfd pfd;
pfd.fd = fd;
pfd.events = f == read ? POLLIN : POLLOUT;
while (n > pos) {
res = (f) (fd, s + pos, n - pos);
switch (res) {
case -1:
if (errno == EINTR)
continue;
#ifdef EWOULDBLOCK
if (errno == EAGAIN || errno == EWOULDBLOCK) {
#else
if (errno == EAGAIN) {
#endif
(void)poll(&pfd, 1, -1);
continue;
}
return 0;
case 0:
errno = EPIPE;
return pos;
default:
pos += (size_t)res;
}
}
return (pos);
}
/*
* ensure all of data on socket comes through. f==readv || f==writev
*/
size_t
pamsshagentauth_atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt)
{
size_t pos = 0, rem;
ssize_t res;
struct iovec iov_array[IOV_MAX] = {{ 0 }};
struct iovec *iov = iov_array;
struct pollfd pfd;
if (iovcnt > IOV_MAX) {
errno = EINVAL;
return 0;
}
/* Make a copy of the iov array because we may modify it below */
memcpy(iov, _iov, iovcnt * sizeof(*_iov));
pfd.fd = fd;
pfd.events = f == readv ? POLLIN : POLLOUT;
for (; iovcnt > 0 && iov[0].iov_len > 0;) {
res = (f) (fd, iov, iovcnt);
switch (res) {
case -1:
if (errno == EINTR)
continue;
#ifdef EWOULDBLOCK
if (errno == EAGAIN || errno == EWOULDBLOCK) {
#else
if (errno == EAGAIN) {
#endif
(void)poll(&pfd, 1, -1);
continue;
}
return 0;
case 0:
errno = EPIPE;
return pos;
default:
rem = (size_t)res;
pos += rem;
/* skip completed iov entries */
while (iovcnt > 0 && rem >= iov[0].iov_len) {
rem -= iov[0].iov_len;
iov++;
iovcnt--;
}
/* This shouldn't happen... */
if (rem > 0 && (iovcnt <= 0 || rem > iov[0].iov_len)) {
errno = EFAULT;
return 0;
}
if (iovcnt == 0)
break;
/* update pointer in partially complete iov */
iov[0].iov_base = ((char *)iov[0].iov_base) + rem;
iov[0].iov_len -= rem;
}
}
return pos;
}

45
atomicio.h Normal file
View File

@ -0,0 +1,45 @@
/* $OpenBSD: atomicio.h,v 1.10 2006/08/03 03:34:41 deraadt Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _ATOMICIO_H
#define _ATOMICIO_H
/*
* Ensure all of data on socket comes through. f==read || f==vwrite
*/
size_t pamsshagentauth_atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
#define vwrite (ssize_t (*)(int, void *, size_t))write
/*
* ensure all of data on socket comes through. f==readv || f==writev
*/
size_t pamsshagentauth_atomiciov(ssize_t (*)(int, const struct iovec *, int),
int, const struct iovec *, int);
#endif /* _ATOMICIO_H */

708
authfd.c Normal file
View File

@ -0,0 +1,708 @@
/* $OpenBSD: authfd.c,v 1.80 2006/08/03 03:34:41 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for connecting the local authentication agent.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 implementation,
* Copyright (c) 2000 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
/*
* All additions/modifications of this file by Jamie Beverly are released under the same license
* as the original version as found in openssh; which is a BSD style license
* */
#include "includes.h"
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pwd.h>
#include <errno.h>
#include "xmalloc.h"
#include "ssh.h"
#include "rsa.h"
#include "buffer.h"
#include "key.h"
#include "authfd.h"
#include "cipher.h"
#include "kex.h"
#include "compat.h"
#include "log.h"
#include "atomicio.h"
#include "misc.h"
static int agent_present = 0;
/* helper */
int pamsshagentauth_decode_reply(int type);
/* macro to check for "agent failure" message */
#define agent_failed(x) \
((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE) || \
(x == SSH2_AGENT_FAILURE))
int
ssh_agent_present(void)
{
if (agent_present)
return 1;
return 0;
}
/* Returns the number of the authentication fd, or -1 if there is none. */
/*
* Added by Jamie Beverly, ensure socket fd points to a socket owned by the user
* A cursory check is done, but to avoid race conditions, it is necessary
* to drop effective UID when connecting to the socket.
*
* If the cause of error is EACCES, because we verified we would not have that
* problem initially, we can safely assume that somebody is attempting to find a
* race condition; so a more "direct" log message is generated.
*/
int
ssh_get_authentication_socket(uid_t uid)
{
const char *authsocket;
int sock;
struct sockaddr_un sunaddr;
struct stat sock_st;
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
if (!authsocket)
return -1;
/* Advisory only; seteuid ensures no race condition; but will only log if we see EACCES */
if( stat(authsocket,&sock_st) == 0) {
if(uid != 0 && sock_st.st_uid != uid) {
pamsshagentauth_fatal("uid %lu attempted to open an agent socket owned by uid %lu", (unsigned long) uid, (unsigned long) sock_st.st_uid);
return -1;
}
}
/*
* Ensures that the EACCES tested for below can _only_ happen if somebody
* is attempting to race the stat above to bypass authentication.
*/
if( (sock_st.st_mode & S_IWUSR) != S_IWUSR || (sock_st.st_mode & S_IRUSR) != S_IRUSR) {
pamsshagentauth_logerror("ssh-agent socket has incorrect permissions for owner");
return -1;
}
sunaddr.sun_family = AF_UNIX;
pamsshagentauth_strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
return -1;
/* close on exec */
if (fcntl(sock, F_SETFD, 1) == -1) {
close(sock);
return -1;
}
errno = 0;
seteuid(uid); /* To ensure a race condition is not used to circumvent the stat
above, we will temporarily drop UID to the caller */
if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) {
close(sock);
if(errno == EACCES)
pamsshagentauth_fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid);
return -1;
}
seteuid(0); /* we now continue the regularly scheduled programming */
agent_present = 1;
return sock;
}
static int
ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply)
{
u_int l, len;
char buf[1024];
/* Get the length of the message, and format it in the buffer. */
len = pamsshagentauth_buffer_len(request);
pamsshagentauth_put_u32(buf, len);
/* Send the length and then the packet to the agent. */
if (pamsshagentauth_atomicio(vwrite, auth->fd, buf, 4) != 4 ||
pamsshagentauth_atomicio(vwrite, auth->fd, pamsshagentauth_buffer_ptr(request),
pamsshagentauth_buffer_len(request)) != pamsshagentauth_buffer_len(request)) {
pamsshagentauth_logerror("Error writing to authentication socket.");
return 0;
}
/*
* Wait for response from the agent. First read the length of the
* response packet.
*/
if (pamsshagentauth_atomicio(read, auth->fd, buf, 4) != 4) {
pamsshagentauth_logerror("Error reading response length from authentication socket.");
return 0;
}
/* Extract the length, and check it for sanity. */
len = pamsshagentauth_get_u32(buf);
if (len > 256 * 1024)
pamsshagentauth_fatal("Authentication response too long: %u", len);
/* Read the rest of the response in to the buffer. */
pamsshagentauth_buffer_clear(reply);
while (len > 0) {
l = len;
if (l > sizeof(buf))
l = sizeof(buf);
if (pamsshagentauth_atomicio(read, auth->fd, buf, l) != l) {
pamsshagentauth_logerror("Error reading response from authentication socket.");
return 0;
}
pamsshagentauth_buffer_append(reply, buf, l);
len -= l;
}
return 1;
}
/*
* Closes the agent socket if it should be closed (depends on how it was
* obtained). The argument must have been returned by
* ssh_get_authentication_socket().
*/
void
ssh_close_authentication_socket(int sock)
{
if (getenv(SSH_AUTHSOCKET_ENV_NAME))
close(sock);
}
/*
* Opens and connects a private socket for communication with the
* authentication agent. Returns the file descriptor (which must be
* shut down and closed by the caller when no longer needed).
* Returns NULL if an error occurred and the connection could not be
* opened.
*/
AuthenticationConnection *
ssh_get_authentication_connection(uid_t uid)
{
AuthenticationConnection *auth;
int sock;
sock = ssh_get_authentication_socket(uid);
/*
* Fail if we couldn't obtain a connection. This happens if we
* exited due to a timeout.
*/
if (sock < 0)
return NULL;
auth = pamsshagentauth_xmalloc(sizeof(*auth));
auth->fd = sock;
pamsshagentauth_buffer_init(&auth->identities);
auth->howmany = 0;
return auth;
}
/*
* Closes the connection to the authentication agent and frees any associated
* memory.
*/
void
ssh_close_authentication_connection(AuthenticationConnection *auth)
{
pamsshagentauth_buffer_free(&auth->identities);
close(auth->fd);
pamsshagentauth_xfree(auth);
}
/* Lock/unlock agent */
int
ssh_lock_agent(AuthenticationConnection *auth, int lock, const char *password)
{
int type;
Buffer msg;
pamsshagentauth_buffer_init(&msg);
pamsshagentauth_buffer_put_char(&msg, lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK);
pamsshagentauth_buffer_put_cstring(&msg, password);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
pamsshagentauth_buffer_free(&msg);
return 0;
}
type = pamsshagentauth_buffer_get_char(&msg);
pamsshagentauth_buffer_free(&msg);
return pamsshagentauth_decode_reply(type);
}
/*
* Returns the first authentication identity held by the agent.
*/
int
ssh_get_num_identities(AuthenticationConnection *auth, int version)
{
int type, code1 = 0, code2 = 0;
Buffer request;
switch (version) {
case 1:
code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER;
break;
case 2:
code1 = SSH2_AGENTC_REQUEST_IDENTITIES;
code2 = SSH2_AGENT_IDENTITIES_ANSWER;
break;
default:
return 0;
}
/*
* Send a message to the agent requesting for a list of the
* identities it can represent.
*/
pamsshagentauth_buffer_init(&request);
pamsshagentauth_buffer_put_char(&request, code1);
pamsshagentauth_buffer_clear(&auth->identities);
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
pamsshagentauth_buffer_free(&request);
return 0;
}
pamsshagentauth_buffer_free(&request);
/* Get message type, and verify that we got a proper answer. */
type = pamsshagentauth_buffer_get_char(&auth->identities);
if (agent_failed(type)) {
return 0;
} else if (type != code2) {
pamsshagentauth_fatal("Bad authentication reply message type: %d", type);
}
/* Get the number of entries in the response and check it for sanity. */
auth->howmany = pamsshagentauth_buffer_get_int(&auth->identities);
if ((u_int)auth->howmany > 1024)
pamsshagentauth_fatal("Too many identities in authentication reply: %d",
auth->howmany);
return auth->howmany;
}
Key *
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
{
/* get number of identities and return the first entry (if any). */
if (ssh_get_num_identities(auth, version) > 0)
return ssh_get_next_identity(auth, comment, version);
return NULL;
}
Key *
ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
{
int keybits;
u_int bits;
u_char *blob;
u_int blen;
Key *key = NULL;
/* Return failure if no more entries. */
if (auth->howmany <= 0)
return NULL;
/*
* Get the next entry from the packet. These will abort with a fatal
* error if the packet is too short or contains corrupt data.
*/
switch (version) {
case 1:
key = pamsshagentauth_key_new(KEY_RSA1);
bits = pamsshagentauth_buffer_get_int(&auth->identities);
pamsshagentauth_buffer_get_bignum(&auth->identities, key->rsa->e);
pamsshagentauth_buffer_get_bignum(&auth->identities, key->rsa->n);
*comment = pamsshagentauth_buffer_get_string(&auth->identities, NULL);
keybits = BN_num_bits(key->rsa->n);
if (keybits < 0 || bits != (u_int)keybits)
pamsshagentauth_logit("Warning: identity keysize mismatch: actual %d, announced %u",
BN_num_bits(key->rsa->n), bits);
break;
case 2:
blob = pamsshagentauth_buffer_get_string(&auth->identities, &blen);
*comment = pamsshagentauth_buffer_get_string(&auth->identities, NULL);
key = pamsshagentauth_key_from_blob(blob, blen);
pamsshagentauth_xfree(blob);
break;
default:
return NULL;
}
/* Decrement the number of remaining entries. */
auth->howmany--;
return key;
}
/*
* Generates a random challenge, sends it to the agent, and waits for
* response from the agent. Returns true (non-zero) if the agent gave the
* correct answer, zero otherwise. Response type selects the style of
* response desired, with 0 corresponding to protocol version 1.0 (no longer
* supported) and 1 corresponding to protocol version 1.1.
*/
int
ssh_decrypt_challenge(AuthenticationConnection *auth,
Key* key, BIGNUM *challenge,
u_char session_id[16],
u_int response_type,
u_char response[16])
{
Buffer buffer;
int success = 0;
int i;
int type;
if (key->type != KEY_RSA1)
return 0;
if (response_type == 0) {
pamsshagentauth_logit("Compatibility with ssh protocol version 1.0 no longer supported.");
return 0;
}
pamsshagentauth_buffer_init(&buffer);
pamsshagentauth_buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
pamsshagentauth_buffer_put_int(&buffer, BN_num_bits(key->rsa->n));
pamsshagentauth_buffer_put_bignum(&buffer, key->rsa->e);
pamsshagentauth_buffer_put_bignum(&buffer, key->rsa->n);
pamsshagentauth_buffer_put_bignum(&buffer, challenge);
pamsshagentauth_buffer_append(&buffer, session_id, 16);
pamsshagentauth_buffer_put_int(&buffer, response_type);
if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
pamsshagentauth_buffer_free(&buffer);
return 0;
}
type = pamsshagentauth_buffer_get_char(&buffer);
if (agent_failed(type)) {
pamsshagentauth_logit("Agent admitted failure to authenticate using the key.");
} else if (type != SSH_AGENT_RSA_RESPONSE) {
pamsshagentauth_fatal("Bad authentication response: %d", type);
} else {
success = 1;
/*
* Get the response from the packet. This will abort with a
* fatal error if the packet is corrupt.
*/
for (i = 0; i < 16; i++)
response[i] = (u_char)pamsshagentauth_buffer_get_char(&buffer);
}
pamsshagentauth_buffer_free(&buffer);
return success;
}
/* ask agent to sign data, returns -1 on error, 0 on success */
int
ssh_agent_sign(AuthenticationConnection *auth,
Key *key,
u_char **sigp, u_int *lenp,
u_char *data, u_int datalen)
{
extern int datafellows;
Buffer msg;
u_char *blob;
u_int blen;
int type, flags = 0;
int ret = -1;
if (pamsshagentauth_key_to_blob(key, &blob, &blen) == 0)
return -1;
if (datafellows & SSH_BUG_SIGBLOB)
flags = SSH_AGENT_OLD_SIGNATURE;
pamsshagentauth_buffer_init(&msg);
pamsshagentauth_buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
pamsshagentauth_buffer_put_string(&msg, blob, blen);
pamsshagentauth_buffer_put_string(&msg, data, datalen);
pamsshagentauth_buffer_put_int(&msg, flags);
pamsshagentauth_xfree(blob);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
pamsshagentauth_buffer_free(&msg);
return -1;
}
type = pamsshagentauth_buffer_get_char(&msg);
if (agent_failed(type)) {
pamsshagentauth_logit("Agent admitted failure to sign using the key.");
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
pamsshagentauth_fatal("Bad authentication response: %d", type);
} else {
ret = 0;
*sigp = pamsshagentauth_buffer_get_string(&msg, lenp);
}
pamsshagentauth_buffer_free(&msg);
return ret;
}
/* Encode key for a message to the agent. */
static void
ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
{
pamsshagentauth_buffer_put_int(b, BN_num_bits(key->n));
pamsshagentauth_buffer_put_bignum(b, key->n);
pamsshagentauth_buffer_put_bignum(b, key->e);
pamsshagentauth_buffer_put_bignum(b, key->d);
/* To keep within the protocol: p < q for ssh. in SSL p > q */
pamsshagentauth_buffer_put_bignum(b, key->iqmp); /* ssh key->u */
pamsshagentauth_buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */
pamsshagentauth_buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */
pamsshagentauth_buffer_put_cstring(b, comment);
}
static void
ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
{
pamsshagentauth_buffer_put_cstring(b, key_ssh_name(key));
switch (key->type) {
case KEY_RSA:
pamsshagentauth_buffer_put_bignum2(b, key->rsa->n);
pamsshagentauth_buffer_put_bignum2(b, key->rsa->e);
pamsshagentauth_buffer_put_bignum2(b, key->rsa->d);
pamsshagentauth_buffer_put_bignum2(b, key->rsa->iqmp);
pamsshagentauth_buffer_put_bignum2(b, key->rsa->p);
pamsshagentauth_buffer_put_bignum2(b, key->rsa->q);
break;
case KEY_DSA:
pamsshagentauth_buffer_put_bignum2(b, key->dsa->p);
pamsshagentauth_buffer_put_bignum2(b, key->dsa->q);
pamsshagentauth_buffer_put_bignum2(b, key->dsa->g);
pamsshagentauth_buffer_put_bignum2(b, key->dsa->pub_key);
pamsshagentauth_buffer_put_bignum2(b, key->dsa->priv_key);
break;
}
pamsshagentauth_buffer_put_cstring(b, comment);
}
/*
* Adds an identity to the authentication server. This call is not meant to
* be used by normal applications.
*/
int
ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
const char *comment, u_int life, u_int confirm)
{
Buffer msg;
int type, constrained = (life || confirm);
pamsshagentauth_buffer_init(&msg);
switch (key->type) {
case KEY_RSA1:
type = constrained ?
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED :
SSH_AGENTC_ADD_RSA_IDENTITY;
pamsshagentauth_buffer_put_char(&msg, type);
ssh_encode_identity_rsa1(&msg, key->rsa, comment);
break;
case KEY_RSA:
case KEY_DSA:
type = constrained ?
SSH2_AGENTC_ADD_ID_CONSTRAINED :
SSH2_AGENTC_ADD_IDENTITY;
pamsshagentauth_buffer_put_char(&msg, type);
ssh_encode_identity_ssh2(&msg, key, comment);
break;
default:
pamsshagentauth_buffer_free(&msg);
return 0;
}
if (constrained) {
if (life != 0) {
pamsshagentauth_buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
pamsshagentauth_buffer_put_int(&msg, life);
}
if (confirm != 0)
pamsshagentauth_buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM);
}
if (ssh_request_reply(auth, &msg, &msg) == 0) {
pamsshagentauth_buffer_free(&msg);
return 0;
}
type = pamsshagentauth_buffer_get_char(&msg);
pamsshagentauth_buffer_free(&msg);
return pamsshagentauth_decode_reply(type);
}
int
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
{
return ssh_add_identity_constrained(auth, key, comment, 0, 0);
}
/*
* Removes an identity from the authentication server. This call is not
* meant to be used by normal applications.
*/
int
ssh_remove_identity(AuthenticationConnection *auth, Key *key)
{
Buffer msg;
int type;
u_char *blob;
u_int blen;
pamsshagentauth_buffer_init(&msg);
if (key->type == KEY_RSA1) {
pamsshagentauth_buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
pamsshagentauth_buffer_put_int(&msg, BN_num_bits(key->rsa->n));
pamsshagentauth_buffer_put_bignum(&msg, key->rsa->e);
pamsshagentauth_buffer_put_bignum(&msg, key->rsa->n);
} else if (key->type == KEY_DSA || key->type == KEY_RSA) {
pamsshagentauth_key_to_blob(key, &blob, &blen);
pamsshagentauth_buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
pamsshagentauth_buffer_put_string(&msg, blob, blen);
pamsshagentauth_xfree(blob);
} else {
pamsshagentauth_buffer_free(&msg);
return 0;
}
if (ssh_request_reply(auth, &msg, &msg) == 0) {
pamsshagentauth_buffer_free(&msg);
return 0;
}
type = pamsshagentauth_buffer_get_char(&msg);
pamsshagentauth_buffer_free(&msg);
return pamsshagentauth_decode_reply(type);
}
int
ssh_update_card(AuthenticationConnection *auth, int add,
const char *reader_id, const char *pin, u_int life, u_int confirm)
{
Buffer msg;
int type, constrained = (life || confirm);
if (add) {
type = constrained ?
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED :
SSH_AGENTC_ADD_SMARTCARD_KEY;
} else
type = SSH_AGENTC_REMOVE_SMARTCARD_KEY;
pamsshagentauth_buffer_init(&msg);
pamsshagentauth_buffer_put_char(&msg, type);
pamsshagentauth_buffer_put_cstring(&msg, reader_id);
pamsshagentauth_buffer_put_cstring(&msg, pin);
if (constrained) {
if (life != 0) {
pamsshagentauth_buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
pamsshagentauth_buffer_put_int(&msg, life);
}
if (confirm != 0)
pamsshagentauth_buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM);
}
if (ssh_request_reply(auth, &msg, &msg) == 0) {
pamsshagentauth_buffer_free(&msg);
return 0;
}
type = pamsshagentauth_buffer_get_char(&msg);
pamsshagentauth_buffer_free(&msg);
return pamsshagentauth_decode_reply(type);
}
/*
* Removes all identities from the agent. This call is not meant to be used
* by normal applications.
*/
int
ssh_remove_all_identities(AuthenticationConnection *auth, int version)
{
Buffer msg;
int type;
int code = (version==1) ?
SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES :
SSH2_AGENTC_REMOVE_ALL_IDENTITIES;
pamsshagentauth_buffer_init(&msg);
pamsshagentauth_buffer_put_char(&msg, code);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
pamsshagentauth_buffer_free(&msg);
return 0;
}
type = pamsshagentauth_buffer_get_char(&msg);
pamsshagentauth_buffer_free(&msg);
return pamsshagentauth_decode_reply(type);
}
int
pamsshagentauth_decode_reply(int type)
{
switch (type) {
case SSH_AGENT_FAILURE:
case SSH_COM_AGENT2_FAILURE:
case SSH2_AGENT_FAILURE:
pamsshagentauth_logit("SSH_AGENT_FAILURE");
return 0;
case SSH_AGENT_SUCCESS:
return 1;
default:
pamsshagentauth_fatal("Bad response from authentication agent: %d", type);
}
/* NOTREACHED */
return 0;
}

95
authfd.h Normal file
View File

@ -0,0 +1,95 @@
/* $OpenBSD: authfd.h,v 1.36 2006/08/03 03:34:41 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions to interface with the SSH_AUTHENTICATION_FD socket.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#ifndef AUTHFD_H
#define AUTHFD_H
/* Messages for the authentication agent connection. */
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
#define SSH_AGENTC_RSA_CHALLENGE 3
#define SSH_AGENT_RSA_RESPONSE 4
#define SSH_AGENT_FAILURE 5
#define SSH_AGENT_SUCCESS 6
#define SSH_AGENTC_ADD_RSA_IDENTITY 7
#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
/* private OpenSSH extensions for SSH2 */
#define SSH2_AGENTC_REQUEST_IDENTITIES 11
#define SSH2_AGENT_IDENTITIES_ANSWER 12
#define SSH2_AGENTC_SIGN_REQUEST 13
#define SSH2_AGENT_SIGN_RESPONSE 14
#define SSH2_AGENTC_ADD_IDENTITY 17
#define SSH2_AGENTC_REMOVE_IDENTITY 18
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
/* smartcard */
#define SSH_AGENTC_ADD_SMARTCARD_KEY 20
#define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
/* lock/unlock the agent */
#define SSH_AGENTC_LOCK 22
#define SSH_AGENTC_UNLOCK 23
/* add key with constraints */
#define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
/* extended failure messages */
#define SSH2_AGENT_FAILURE 30
/* additional error code for ssh.com's ssh-agent2 */
#define SSH_COM_AGENT2_FAILURE 102
#define SSH_AGENT_OLD_SIGNATURE 0x01
typedef struct {
int fd;
Buffer identities;
int howmany;
} AuthenticationConnection;
int ssh_agent_present(void);
int ssh_get_authentication_socket(uid_t);
void ssh_close_authentication_socket(int);
AuthenticationConnection *ssh_get_authentication_connection(uid_t uid);
void ssh_close_authentication_connection(AuthenticationConnection *);
int ssh_get_num_identities(AuthenticationConnection *, int);
Key *ssh_get_first_identity(AuthenticationConnection *, char **, int);
Key *ssh_get_next_identity(AuthenticationConnection *, char **, int);
int ssh_add_identity(AuthenticationConnection *, Key *, const char *);
int ssh_add_identity_constrained(AuthenticationConnection *, Key *,
const char *, u_int, u_int);
int ssh_remove_identity(AuthenticationConnection *, Key *);
int ssh_remove_all_identities(AuthenticationConnection *, int);
int ssh_lock_agent(AuthenticationConnection *, int, const char *);
int ssh_update_card(AuthenticationConnection *, int, const char *,
const char *, u_int, u_int);
int
ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16],
u_int, u_char[16]);
int
ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, u_int *, u_char *,
u_int);
#endif /* AUTHFD_H */

249
bufaux.c Normal file
View File

@ -0,0 +1,249 @@
/* $OpenBSD: bufaux.c,v 1.44 2006/08/03 03:34:41 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Auxiliary functions for storing and retrieving various data types to/from
* Buffers.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* SSH2 packet format added by Markus Friedl
* Copyright (c) 2000 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "includes.h"
#include <sys/types.h>
#include <openssl/bn.h>
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
/*
* Returns integers from the buffer (msb first).
*/
int
pamsshagentauth_buffer_get_short_ret(u_short *ret, Buffer *buffer)
{
u_char buf[2];
if (pamsshagentauth_buffer_get_ret(buffer, (char *) buf, 2) == -1)
return (-1);
*ret = pamsshagentauth_get_u16(buf);
return (0);
}
u_short
pamsshagentauth_buffer_get_short(Buffer *buffer)
{
u_short ret;
if (pamsshagentauth_buffer_get_short_ret(&ret, buffer) == -1)
pamsshagentauth_fatal("buffer_get_short: buffer error");
return (ret);
}
int
pamsshagentauth_buffer_get_int_ret(u_int *ret, Buffer *buffer)
{
u_char buf[4];
if (pamsshagentauth_buffer_get_ret(buffer, (char *) buf, 4) == -1)
return (-1);
*ret = pamsshagentauth_get_u32(buf);
return (0);
}
u_int
pamsshagentauth_buffer_get_int(Buffer *buffer)
{
u_int ret;
if (pamsshagentauth_buffer_get_int_ret(&ret, buffer) == -1)
pamsshagentauth_fatal("buffer_get_int: buffer error");
return (ret);
}
int
pamsshagentauth_buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer)
{
u_char buf[8];
if (pamsshagentauth_buffer_get_ret(buffer, (char *) buf, 8) == -1)
return (-1);
*ret = pamsshagentauth_get_u64(buf);
return (0);
}
u_int64_t
pamsshagentauth_buffer_get_int64(Buffer *buffer)
{
u_int64_t ret;
if (pamsshagentauth_buffer_get_int64_ret(&ret, buffer) == -1)
pamsshagentauth_fatal("buffer_get_int: buffer error");
return (ret);
}
/*
* Stores integers in the buffer, msb first.
*/
void
pamsshagentauth_buffer_put_short(Buffer *buffer, u_short value)
{
char buf[2];
pamsshagentauth_put_u16(buf, value);
pamsshagentauth_buffer_append(buffer, buf, 2);
}
void
pamsshagentauth_buffer_put_int(Buffer *buffer, u_int value)
{
char buf[4];
pamsshagentauth_put_u32(buf, value);
pamsshagentauth_buffer_append(buffer, buf, 4);
}
void
pamsshagentauth_buffer_put_int64(Buffer *buffer, u_int64_t value)
{
char buf[8];
pamsshagentauth_put_u64(buf, value);
pamsshagentauth_buffer_append(buffer, buf, 8);
}
/*
* Returns an arbitrary binary string from the buffer. The string cannot
* be longer than 256k. The returned value points to memory allocated
* with xmalloc; it is the responsibility of the calling function to free
* the data. If length_ptr is non-NULL, the length of the returned data
* will be stored there. A null character will be automatically appended
* to the returned string, and is not counted in length.
*/
void *
pamsshagentauth_buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
{
u_char *value;
u_int len;
/* Get the length. */
len = pamsshagentauth_buffer_get_int(buffer);
if (len > 256 * 1024) {
pamsshagentauth_logerror("buffer_get_string_ret: bad string length %u", len);
return (NULL);
}
/* Allocate space for the string. Add one byte for a null character. */
value = pamsshagentauth_xmalloc(len + 1);
/* Get the string. */
if (pamsshagentauth_buffer_get_ret(buffer, value, len) == -1) {
pamsshagentauth_logerror("buffer_get_string_ret: buffer_get failed");
pamsshagentauth_xfree(value);
return (NULL);
}
/* Append a null character to make processing easier. */
value[len] = 0;
/* Optionally return the length of the string. */
if (length_ptr)
*length_ptr = len;
return (value);
}
void *
pamsshagentauth_buffer_get_string(Buffer *buffer, u_int *length_ptr)
{
void *ret;
if ((ret = pamsshagentauth_buffer_get_string_ret(buffer, length_ptr)) == NULL)
pamsshagentauth_fatal("buffer_get_string: buffer error");
return (ret);
}
/*
* Stores and arbitrary binary string in the buffer.
*/
void
pamsshagentauth_buffer_put_string(Buffer *buffer, const void *buf, u_int len)
{
pamsshagentauth_buffer_put_int(buffer, len);
pamsshagentauth_buffer_append(buffer, buf, len);
}
void
pamsshagentauth_buffer_put_cstring(Buffer *buffer, const char *s)
{
if (s == NULL)
pamsshagentauth_fatal("buffer_put_cstring: s == NULL");
pamsshagentauth_buffer_put_string(buffer, s, strlen(s));
}
/*
* Returns a character from the buffer (0 - 255).
*/
int
pamsshagentauth_buffer_get_char_ret(char *ret, Buffer *buffer)
{
if (pamsshagentauth_buffer_get_ret(buffer, ret, 1) == -1) {
pamsshagentauth_logerror("buffer_get_char_ret: buffer_get_ret failed");
return (-1);
}
return (0);
}
int
pamsshagentauth_buffer_get_char(Buffer *buffer)
{
char ch;
if (pamsshagentauth_buffer_get_char_ret(&ch, buffer) == -1)
pamsshagentauth_fatal("buffer_get_char: buffer error");
return (u_char) ch;
}
/*
* Stores a character in the buffer.
*/
void
pamsshagentauth_buffer_put_char(Buffer *buffer, int value)
{
char ch = value;
pamsshagentauth_buffer_append(buffer, &ch, 1);
}

223
bufbn.c Normal file
View File

@ -0,0 +1,223 @@
/* $OpenBSD: bufbn.c,v 1.6 2007/06/02 09:04:58 djm Exp $*/
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Auxiliary functions for storing and retrieving various data types to/from
* Buffers.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* SSH2 packet format added by Markus Friedl
* Copyright (c) 2000 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "includes.h"
#include <sys/types.h>
#include <openssl/bn.h>
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
/*
* Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
* by (bits+7)/8 bytes of binary data, msb first.
*/
int
pamsshagentauth_buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
{
int bits = BN_num_bits(value);
int bin_size = (bits + 7) / 8;
u_char *buf = pamsshagentauth_xmalloc(bin_size);
int oi;
char msg[2];
/* Get the value of in binary */
oi = BN_bn2bin(value, buf);
if (oi != bin_size) {
pamsshagentauth_logerror("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d",
oi, bin_size);
pamsshagentauth_xfree(buf);
return (-1);
}
/* Store the number of bits in the buffer in two bytes, msb first. */
pamsshagentauth_put_u16(msg, bits);
pamsshagentauth_buffer_append(buffer, msg, 2);
/* Store the binary data. */
pamsshagentauth_buffer_append(buffer, buf, oi);
memset(buf, 0, bin_size);
pamsshagentauth_xfree(buf);
return (0);
}
void
pamsshagentauth_buffer_put_bignum(Buffer *buffer, const BIGNUM *value)
{
if (pamsshagentauth_buffer_put_bignum_ret(buffer, value) == -1)
pamsshagentauth_fatal("buffer_put_bignum: buffer error");
}
/*
* Retrieves a BIGNUM from the buffer.
*/
int
pamsshagentauth_buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
{
u_int bits, bytes;
u_char buf[2], *bin;
/* Get the number of bits. */
if (pamsshagentauth_buffer_get_ret(buffer, (char *) buf, 2) == -1) {
pamsshagentauth_logerror("buffer_get_bignum_ret: invalid length");
return (-1);
}
bits = pamsshagentauth_get_u16(buf);
/* Compute the number of binary bytes that follow. */
bytes = (bits + 7) / 8;
if (bytes > 8 * 1024) {
pamsshagentauth_logerror("buffer_get_bignum_ret: cannot handle BN of size %d", bytes);
return (-1);
}
if (pamsshagentauth_buffer_len(buffer) < bytes) {
pamsshagentauth_logerror("buffer_get_bignum_ret: input buffer too small");
return (-1);
}
bin = pamsshagentauth_buffer_ptr(buffer);
if (BN_bin2bn(bin, bytes, value) == NULL) {
pamsshagentauth_logerror("buffer_get_bignum_ret: BN_bin2bn failed");
return (-1);
}
if (pamsshagentauth_buffer_consume_ret(buffer, bytes) == -1) {
pamsshagentauth_logerror("buffer_get_bignum_ret: buffer_consume failed");
return (-1);
}
return (0);
}
void
pamsshagentauth_buffer_get_bignum(Buffer *buffer, BIGNUM *value)
{
if (pamsshagentauth_buffer_get_bignum_ret(buffer, value) == -1)
pamsshagentauth_fatal("buffer_get_bignum: buffer error");
}
/*
* Stores a BIGNUM in the buffer in SSH2 format.
*/
int
pamsshagentauth_buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
{
u_int bytes;
u_char *buf;
int oi;
u_int hasnohigh = 0;
if (BN_is_zero(value)) {
pamsshagentauth_buffer_put_int(buffer, 0);
return 0;
}
if (value->neg) {
pamsshagentauth_logerror("buffer_put_bignum2_ret: negative numbers not supported");
return (-1);
}
bytes = BN_num_bytes(value) + 1; /* extra padding byte */
if (bytes < 2) {
pamsshagentauth_logerror("buffer_put_bignum2_ret: BN too small");
return (-1);
}
buf = pamsshagentauth_xmalloc(bytes);
buf[0] = 0x00;
/* Get the value of in binary */
oi = BN_bn2bin(value, buf+1);
if (oi < 0 || (u_int)oi != bytes - 1) {
pamsshagentauth_logerror("buffer_put_bignum2_ret: BN_bn2bin() failed: "
"oi %d != bin_size %d", oi, bytes);
pamsshagentauth_xfree(buf);
return (-1);
}
hasnohigh = (buf[1] & 0x80) ? 0 : 1;
pamsshagentauth_buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
memset(buf, 0, bytes);
pamsshagentauth_xfree(buf);
return (0);
}
void
pamsshagentauth_buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
{
if (pamsshagentauth_buffer_put_bignum2_ret(buffer, value) == -1)
pamsshagentauth_fatal("buffer_put_bignum2: buffer error");
}
int
pamsshagentauth_buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
{
u_int len;
u_char *bin;
if ((bin = pamsshagentauth_buffer_get_string_ret(buffer, &len)) == NULL) {
pamsshagentauth_logerror("buffer_get_bignum2_ret: invalid bignum");
return (-1);
}
if (len > 0 && (bin[0] & 0x80)) {
pamsshagentauth_logerror("buffer_get_bignum2_ret: negative numbers not supported");
pamsshagentauth_xfree(bin);
return (-1);
}
if (len > 8 * 1024) {
pamsshagentauth_logerror("buffer_get_bignum2_ret: cannot handle BN of size %d",
len);
pamsshagentauth_xfree(bin);
return (-1);
}
if (BN_bin2bn(bin, len, value) == NULL) {
pamsshagentauth_logerror("buffer_get_bignum2_ret: BN_bin2bn failed");
pamsshagentauth_xfree(bin);
return (-1);
}
pamsshagentauth_xfree(bin);
return (0);
}
void
pamsshagentauth_buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
{
if (pamsshagentauth_buffer_get_bignum2_ret(buffer, value) == -1)
pamsshagentauth_fatal("buffer_get_bignum2: buffer error");
}

252
buffer.c Normal file
View File

@ -0,0 +1,252 @@
/* $OpenBSD: buffer.c,v 1.31 2006/08/03 03:34:41 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for manipulating fifo buffers (that can grow if needed).
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
#include <sys/param.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#define BUFFER_MAX_CHUNK 0x100000
#define BUFFER_MAX_LEN 0xa00000
#define BUFFER_ALLOCSZ 0x008000
/* Initializes the buffer structure. */
void
pamsshagentauth_buffer_init(Buffer *buffer)
{
const u_int len = 4096;
buffer->alloc = 0;
buffer->buf = pamsshagentauth_xmalloc(len);
buffer->alloc = len;
buffer->offset = 0;
buffer->end = 0;
}
/* Frees any memory used for the buffer. */
void
pamsshagentauth_buffer_free(Buffer *buffer)
{
if (buffer->alloc > 0) {
memset(buffer->buf, 0, buffer->alloc);
buffer->alloc = 0;
pamsshagentauth_xfree(buffer->buf);
}
}
/*
* Clears any data from the buffer, making it empty. This does not actually
* zero the memory.
*/
void
pamsshagentauth_buffer_clear(Buffer *buffer)
{
buffer->offset = 0;
buffer->end = 0;
}
/* Appends data to the buffer, expanding it if necessary. */
void
pamsshagentauth_buffer_append(Buffer *buffer, const void *data, u_int len)
{
void *p;
p = pamsshagentauth_buffer_append_space(buffer, len);
memcpy(p, data, len);
}
static int
buffer_compact(Buffer *buffer)
{
/*
* If the buffer is quite empty, but all data is at the end, move the
* data to the beginning.
*/
if (buffer->offset > MIN(buffer->alloc, BUFFER_MAX_CHUNK)) {
memmove(buffer->buf, buffer->buf + buffer->offset,
buffer->end - buffer->offset);
buffer->end -= buffer->offset;
buffer->offset = 0;
return (1);
}
return (0);
}
/*
* Appends space to the buffer, expanding the buffer if necessary. This does
* not actually copy the data into the buffer, but instead returns a pointer
* to the allocated region.
*/
void *
pamsshagentauth_buffer_append_space(Buffer *buffer, u_int len)
{
u_int newlen;
void *p;
if (len > BUFFER_MAX_CHUNK)
pamsshagentauth_fatal("buffer_append_space: len %u not supported", len);
/* If the buffer is empty, start using it from the beginning. */
if (buffer->offset == buffer->end) {
buffer->offset = 0;
buffer->end = 0;
}
restart:
/* If there is enough space to store all data, store it now. */
if (buffer->end + len < buffer->alloc) {
p = buffer->buf + buffer->end;
buffer->end += len;
return p;
}
/* Compact data back to the start of the buffer if necessary */
if (buffer_compact(buffer))
goto restart;
/* Increase the size of the buffer and retry. */
newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ);
if (newlen > BUFFER_MAX_LEN)
pamsshagentauth_fatal("buffer_append_space: alloc %u not supported",
newlen);
buffer->buf = pamsshagentauth_xrealloc(buffer->buf, 1, newlen);
buffer->alloc = newlen;
goto restart;
/* NOTREACHED */
}
/*
* Check whether an allocation of 'len' will fit in the buffer
* This must follow the same math as buffer_append_space
*/
int
pamsshagentauth_buffer_check_alloc(Buffer *buffer, u_int len)
{
if (buffer->offset == buffer->end) {
buffer->offset = 0;
buffer->end = 0;
}
restart:
if (buffer->end + len < buffer->alloc)
return (1);
if (buffer_compact(buffer))
goto restart;
if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN)
return (1);
return (0);
}
/* Returns the number of bytes of data in the buffer. */
u_int
pamsshagentauth_buffer_len(Buffer *buffer)
{
return buffer->end - buffer->offset;
}
/* Gets data from the beginning of the buffer. */
int
pamsshagentauth_buffer_get_ret(Buffer *buffer, void *buf, u_int len)
{
if (len > buffer->end - buffer->offset) {
pamsshagentauth_logerror("buffer_get_ret: trying to get more bytes %d than in buffer %d",
len, buffer->end - buffer->offset);
return (-1);
}
memcpy(buf, buffer->buf + buffer->offset, len);
buffer->offset += len;
return (0);
}
void
pamsshagentauth_buffer_get(Buffer *buffer, void *buf, u_int len)
{
if (pamsshagentauth_buffer_get_ret(buffer, buf, len) == -1)
pamsshagentauth_fatal("buffer_get: buffer error");
}
/* Consumes the given number of bytes from the beginning of the buffer. */
int
pamsshagentauth_buffer_consume_ret(Buffer *buffer, u_int bytes)
{
if (bytes > buffer->end - buffer->offset) {
pamsshagentauth_logerror("buffer_consume_ret: trying to get more bytes than in buffer");
return (-1);
}
buffer->offset += bytes;
return (0);
}
void
pamsshagentauth_buffer_consume(Buffer *buffer, u_int bytes)
{
if (pamsshagentauth_buffer_consume_ret(buffer, bytes) == -1)
pamsshagentauth_fatal("buffer_consume: buffer error");
}
/* Consumes the given number of bytes from the end of the buffer. */
int
pamsshagentauth_buffer_consume_end_ret(Buffer *buffer, u_int bytes)
{
if (bytes > buffer->end - buffer->offset)
return (-1);
buffer->end -= bytes;
return (0);
}
void
pamsshagentauth_buffer_consume_end(Buffer *buffer, u_int bytes)
{
if (pamsshagentauth_buffer_consume_end_ret(buffer, bytes) == -1)
pamsshagentauth_fatal("buffer_consume_end: trying to get more bytes than in buffer");
}
/* Returns a pointer to the first used byte in the buffer. */
void *
pamsshagentauth_buffer_ptr(Buffer *buffer)
{
return buffer->buf + buffer->offset;
}
/* Dumps the contents of the buffer to stderr. */
void
pamsshagentauth_buffer_dump(Buffer *buffer)
{
u_int i;
u_char *ucp = buffer->buf;
for (i = buffer->offset; i < buffer->end; i++) {
fprintf(stderr, "%02x", ucp[i]);
if ((i-buffer->offset)%16==15)
fprintf(stderr, "\r\n");
else if ((i-buffer->offset)%2==1)
fprintf(stderr, " ");
}
fprintf(stderr, "\r\n");
}

85
buffer.h Normal file
View File

@ -0,0 +1,85 @@
/* $OpenBSD: buffer.h,v 1.16 2006/08/03 03:34:41 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Code for manipulating FIFO buffers.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#ifndef BUFFER_H
#define BUFFER_H
typedef struct {
u_char *buf; /* Buffer for data. */
u_int alloc; /* Number of bytes allocated for data. */
u_int offset; /* Offset of first byte containing data. */
u_int end; /* Offset of last byte containing data. */
} Buffer;
void pamsshagentauth_buffer_init(Buffer *);
void pamsshagentauth_buffer_clear(Buffer *);
void pamsshagentauth_buffer_free(Buffer *);
u_int pamsshagentauth_buffer_len(Buffer *);
void *pamsshagentauth_buffer_ptr(Buffer *);
void pamsshagentauth_buffer_append(Buffer *, const void *, u_int);
void *pamsshagentauth_buffer_append_space(Buffer *, u_int);
int pamsshagentauth_buffer_check_alloc(Buffer *, u_int);
void pamsshagentauth_buffer_get(Buffer *, void *, u_int);
void pamsshagentauth_buffer_consume(Buffer *, u_int);
void pamsshagentauth_buffer_consume_end(Buffer *, u_int);
void pamsshagentauth_buffer_dump(Buffer *);
int pamsshagentauth_buffer_get_ret(Buffer *, void *, u_int);
int pamsshagentauth_buffer_consume_ret(Buffer *, u_int);
int pamsshagentauth_buffer_consume_end_ret(Buffer *, u_int);
#include <openssl/bn.h>
void pamsshagentauth_buffer_put_bignum(Buffer *, const BIGNUM *);
void pamsshagentauth_buffer_put_bignum2(Buffer *, const BIGNUM *);
void pamsshagentauth_buffer_get_bignum(Buffer *, BIGNUM *);
void pamsshagentauth_buffer_get_bignum2(Buffer *, BIGNUM *);
u_short pamsshagentauth_buffer_get_short(Buffer *);
void pamsshagentauth_buffer_put_short(Buffer *, u_short);
u_int pamsshagentauth_buffer_get_int(Buffer *);
void pamsshagentauth_buffer_put_int(Buffer *, u_int);
u_int64_t pamsshagentauth_buffer_get_int64(Buffer *);
void pamsshagentauth_buffer_put_int64(Buffer *, u_int64_t);
int pamsshagentauth_buffer_get_char(Buffer *);
void pamsshagentauth_buffer_put_char(Buffer *, int);
void *pamsshagentauth_buffer_get_string(Buffer *, u_int *);
void pamsshagentauth_buffer_put_string(Buffer *, const void *, u_int);
void pamsshagentauth_buffer_put_cstring(Buffer *, const char *);
#define buffer_skip_string(b) \
do { u_int l = pamsshagentauth_buffer_get_int(b); pamsshagentauth_buffer_consume(b, l); } while (0)
int pamsshagentauth_buffer_put_bignum_ret(Buffer *, const BIGNUM *);
int pamsshagentauth_buffer_get_bignum_ret(Buffer *, BIGNUM *);
int pamsshagentauth_buffer_put_bignum2_ret(Buffer *, const BIGNUM *);
int pamsshagentauth_buffer_get_bignum2_ret(Buffer *, BIGNUM *);
int pamsshagentauth_buffer_get_short_ret(u_short *, Buffer *);
int pamsshagentauth_buffer_get_int_ret(u_int *, Buffer *);
int pamsshagentauth_buffer_get_int64_ret(u_int64_t *, Buffer *);
void *pamsshagentauth_buffer_get_string_ret(Buffer *, u_int *);
int pamsshagentauth_buffer_get_char_ret(char *, Buffer *);
#endif /* BUFFER_H */

91
cipher.h Normal file
View File

@ -0,0 +1,91 @@
/* $OpenBSD: cipher.h,v 1.36 2006/03/25 22:22:42 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* Copyright (c) 2000 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CIPHER_H
#define CIPHER_H
#include <openssl/evp.h>
/*
* Cipher types for SSH-1. New types can be added, but old types should not
* be removed for compatibility. The maximum allowed value is 31.
*/
#define SSH_CIPHER_SSH2 -3
#define SSH_CIPHER_INVALID -2 /* No valid cipher selected. */
#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */
#define SSH_CIPHER_NONE 0 /* no encryption */
#define SSH_CIPHER_IDEA 1 /* IDEA CFB */
#define SSH_CIPHER_DES 2 /* DES CBC */
#define SSH_CIPHER_3DES 3 /* 3DES CBC */
#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */
#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
#define SSH_CIPHER_BLOWFISH 6
#define SSH_CIPHER_RESERVED 7
#define SSH_CIPHER_MAX 31
#define CIPHER_ENCRYPT 1
#define CIPHER_DECRYPT 0
typedef struct Cipher Cipher;
typedef struct CipherContext CipherContext;
struct Cipher;
struct CipherContext {
int plaintext;
EVP_CIPHER_CTX evp;
Cipher *cipher;
};
u_int cipher_mask_ssh1(int);
Cipher *cipher_by_name(const char *);
Cipher *cipher_by_number(int);
int cipher_number(const char *);
char *cipher_name(int);
int ciphers_valid(const char *);
void cipher_init(CipherContext *, Cipher *, const u_char *, u_int,
const u_char *, u_int, int);
void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int);
void cipher_cleanup(CipherContext *);
void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
u_int cipher_blocksize(const Cipher *);
u_int cipher_keylen(const Cipher *);
u_int cipher_get_number(const Cipher *);
void cipher_get_keyiv(CipherContext *, u_char *, u_int);
void cipher_set_keyiv(CipherContext *, u_char *);
int cipher_get_keyiv_len(const CipherContext *);
int cipher_get_keycontext(const CipherContext *, u_char *);
void cipher_set_keycontext(CipherContext *, u_char *);
#endif /* CIPHER_H */

32
cleanup.c Normal file
View File

@ -0,0 +1,32 @@
/* $OpenBSD: cleanup.c,v 1.5 2006/08/03 03:34:42 deraadt Exp $ */
/*
* Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdarg.h>
#include "log.h"
/* default implementation */
void
pamsshagentauth_cleanup_exit(int i)
{
_exit(i);
}

26
compat.c Normal file
View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2000 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
int datafellows = 0;
int compat13 = 0;
int compat20 = 0;

70
compat.h Normal file
View File

@ -0,0 +1,70 @@
/* $OpenBSD: compat.h,v 1.41 2006/12/12 03:58:42 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef COMPAT_H
#define COMPAT_H
#define SSH_PROTO_UNKNOWN 0x00
#define SSH_PROTO_1 0x01
#define SSH_PROTO_1_PREFERRED 0x02
#define SSH_PROTO_2 0x04
#define SSH_BUG_SIGBLOB 0x00000001
#define SSH_BUG_PKSERVICE 0x00000002
#define SSH_BUG_HMAC 0x00000004
#define SSH_BUG_X11FWD 0x00000008
#define SSH_OLD_SESSIONID 0x00000010
#define SSH_BUG_PKAUTH 0x00000020
#define SSH_BUG_DEBUG 0x00000040
#define SSH_BUG_BANNER 0x00000080
#define SSH_BUG_IGNOREMSG 0x00000100
#define SSH_BUG_PKOK 0x00000200
#define SSH_BUG_PASSWORDPAD 0x00000400
#define SSH_BUG_SCANNER 0x00000800
#define SSH_BUG_BIGENDIANAES 0x00001000
#define SSH_BUG_RSASIGMD5 0x00002000
#define SSH_OLD_DHGEX 0x00004000
#define SSH_BUG_NOREKEY 0x00008000
#define SSH_BUG_HBSERVICE 0x00010000
#define SSH_BUG_OPENFAILURE 0x00020000
#define SSH_BUG_DERIVEKEY 0x00040000
#define SSH_BUG_DUMMYCHAN 0x00100000
#define SSH_BUG_EXTEOF 0x00200000
#define SSH_BUG_PROBE 0x00400000
#define SSH_BUG_FIRSTKEX 0x00800000
#define SSH_OLD_FORWARD_ADDR 0x01000000
#define SSH_BUG_RFWD_ADDR 0x02000000
void enable_compat13(void);
void enable_compat20(void);
void compat_datafellows(const char *);
int proto_spec(const char *);
char *compat_cipher_proposal(char *);
extern int compat13;
extern int compat20;
extern int datafellows;
#endif

1530
config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

1496
config.h.in Normal file

File diff suppressed because it is too large Load Diff

1773
config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

17025
configure vendored Executable file

File diff suppressed because it is too large Load Diff

3111
configure.ac Normal file

File diff suppressed because it is too large Load Diff

42
debian/README vendored Normal file
View File

@ -0,0 +1,42 @@
The Debian Package pam-ssh-agent-auth
----------------------------
pam_ssh_agent_auth is a PAM module which permits PAM authentication via your
keyring in a forwarded ssh-agent.
Release 0.10.2 is stable, and has been tested on FreeBSD, Solaris 10, Solaris 11,
RHEL5, RHEL6, Debian Wheezy, Ubuntu 12.04 (LTS), Ubuntu 13.10,
and MacOS X 10.7.
This module can be used to provide authentication for anything run locally that
supports PAM. It was written specifically with the intention of permitting
authentication for sudo without password entry, and also has been proven useful
for use with su as an alternative to wheel.
It serves as middle ground between the two most common, and suboptimal
alternatives for large-scale system administration: allowing rootlogin via ssh,
or using NOPASSWD in sudoers. This module allows for ssh public-key
authentication, and it does this by leveraging an authentication mechanism you
are probably already using, ssh-agent.
There are caveats of course, ssh-agent forwarding has its own security risks
which must be carefully considered for your environment. In cases where there
are not untrustworthy intermediate servers, and you wish to retain traceability,
accountability, and required authentication for privileged command invocation,
the benefits should outweigh the risks. Release 0.10.2 can be downloaded from
SourceForge: https://sourceforge.net/project/showfiles.php?group_id=249556
If you encounter any issues with usability or security, please use the project's
SourceForge tracker:
https://sourceforge.net/tracker2/?group_id=249556&atid=1126337
Note that if you wish to use this for sudo, you will need a version of sudo that
preserves the env_keep environment during authentication; and ideally a version
incorporating my minor patch which ensures RUSER is set during PAM authentication.
sudo 1.6.8p12 does not work correctly with this PAM module, because it clears the
environment (even env_keep variables) prior to attempting PAM authentication.
sudo 1.7.2p1 or later is preferred, as it correctly sets PAM_RUSER for
authentication.
-- Jamie Beverly <soupboy@sourceforge.net> Wed, 13 Jan 2010 01:08:49 +0300

43
debian/changelog vendored Normal file
View File

@ -0,0 +1,43 @@
pam-ssh-agent-auth (0.10.2-1) stable; urgency=low
* fix autoconf to work with autoreconf -fi
* correct sudo-version note in man page
* fix wire-protocol issue if a call fails
* add licensing information to files missing it
* correct licensing in debian files
* fix compiler warnings with -D_FORTIFY_SOURCE=2
* fix compiler warnings with -Wunused-parameter
-- Jamie Beverly <soupboy@sourceforge.net> Thu, 9 Jan 2014 06:23:00 -0800
pam-ssh-agent-auth (0.10.1-1) stable; urgency=low
* support for authorized_keys_command and authorized_keys_command_user
-- Jamie Beverly <soupboy@sourceforge.net> Thu, 9 Jan 2014 06:23:00 -0800
pam-ssh-agent-auth (0.9.6-1) stable; urgency=high
* Bug that allowed random cookie to be zero length, which could permit replay attacks
* Inclusion of additional metadata in session-id of request sent to ssh-agent to permit chain of trust
* symbol-rename for base64
-- Jamie Beverly <soupboy@sourceforge.net> Sun, 22 Sep 2013 15:25:00 -0700
pam-ssh-agent-auth (0.9.5-1) stable; urgency=low
* Portability fixes for BSD/Mac
-- Jamie Beverly <soupboy@sourceforge.net> Thu, 21 Feb 2013 18:12:00 -0800
pam-ssh-agent-auth (0.9.4-1) stable; urgency=low
* Prefixed symbol names to avoid collision with globally dl_open'd symbols names
* updated Makefile.in as per http://sourceforge.net/tracker/?func=detail&aid=3510464&group_id=249556&atid=1126337
* updated documentation for pam configuration
-- Jamie Beverly <soupboy@sourceforge.net> Wed, 26 Jun 2012 19:22:00 -0700
pam-ssh-agent-auth (0.9.3-1) stable; urgency=low
* Minor fixes
* changed default logging to include key signature and key file output (was
previously in 'debug' mode)
-- Jamie Beverly <soupboy@sourceforge.net> Wed, 07 Jun 2011 11:10:00 -0700
pam-ssh-agent-auth (0.9.2-1) stable; urgency=low
* Initial Release.
-- Jamie Beverly <soupboy@sourceforge.net> Wed, 13 Jan 2010 01:08:49 -0300

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
7

20
debian/control vendored Normal file
View File

@ -0,0 +1,20 @@
Source: pam-ssh-agent-auth
Priority: extra
Maintainer: Jamie Beverly <soupboy@sourceforge.net>
Build-Depends: debhelper (>= 7), autotools-dev, libssl-dev, libpam0g-dev
Standards-Version: 3.8.0
Section: libs
Homepage: http://pamsshagentauth.sf.net/
Package: pam-ssh-agent-auth
Section: admin
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: PAM Authentication via forwarded ssh-agent
pam_ssh_agent_auth is a PAM module which permits PAM authentication via your
keyring in a forwarded ssh-agent.
This module can be used to provide authentication for anything run locally that
supports PAM. It was written specifically with the intention of permitting
authentication for sudo without password entry, and also has been proven useful
for use with su as an alternative to wheel.

41
debian/copyright vendored Normal file
View File

@ -0,0 +1,41 @@
This package was debianized by Jamie Beverly <soupboy@sourceforge.net> on
Wed, 13 Jan 2010 01:08:49 +0300.
It was downloaded from http://pamsshagentauth.sf.net/
Copyright:
Copyright (C) 2008 Jamie Beverly
License:
Copyright (c) 2008, Jamie Beverly.
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.
THIS SOFTWARE IS PROVIDED BY Jamie Beverly ``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 Jamie Beverly 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 Jamie Beverly.
The Debian packaging is copyright 2010, Jamie Beverly <soupboy@sourceforge.net> and
is licensed under the GPL, see `/usr/share/common-licenses/GPL-2'.

1
debian/dirs vendored Normal file
View File

@ -0,0 +1 @@
lib/security

1
debian/pam-ssh-agent-auth.dirs vendored Normal file
View File

@ -0,0 +1 @@
lib/security

1
debian/pam-ssh-agent-auth.files vendored Normal file
View File

@ -0,0 +1 @@
lib/security/pam_ssh_agent_auth.so

1
debian/pam-ssh-agent-auth.install vendored Normal file
View File

@ -0,0 +1 @@
lib/security/pam_ssh_agent_auth.so

1
debian/pam-ssh-agent-auth.manpages vendored Normal file
View File

@ -0,0 +1 @@
pam_ssh_agent_auth.8

113
debian/rules vendored Executable file
View File

@ -0,0 +1,113 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
# These are used for cross-compiling and for saving the configure script
# from having to guess our platform (since we know it already)
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
else
CROSS= --build $(DEB_BUILD_GNU_TYPE)
endif
# shared library versions, option 1
version=2.0.5
major=2
# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so
#version=`ls src/.libs/lib*.so.* | \
# awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
#major=`ls src/.libs/lib*.so.* | \
# awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
config.status: configure
dh_testdir
# Add here commands to configure the package.
ifneq "$(wildcard /usr/share/misc/config.sub)" ""
cp -f /usr/share/misc/config.sub config.sub
endif
ifneq "$(wildcard /usr/share/misc/config.guess)" ""
cp -f /usr/share/misc/config.guess config.guess
endif
./configure $(CROSS) --prefix=/usr --libexecdir=/lib/security --with-mantype=man --mandir=/usr//share/man --infodir=/usr/share/info CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs"
build: build-stamp
build-stamp: config.status
dh_testdir
# Add here commands to compile the package.
$(MAKE)
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp
# Add here commands to clean up after the build process.
[ ! -f Makefile ] || $(MAKE) distclean
rm -f config.sub config.guess
dh_clean
install: build
dh_testdir
dh_testroot
dh_prep
dh_installdirs
# Add here commands to install the package into debian/tmp
$(MAKE) DESTDIR=$(CURDIR)/debian/tmp prefix=$(CURDIR)/debian/tmp/usr install
# Build architecture-independent files here.
binary-indep: install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: install
dh_testdir
dh_testroot
dh_installchangelogs
dh_installdocs
dh_installexamples
dh_install
# dh_installmenu
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman -A
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_python
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install

732
defines.h Normal file
View File

@ -0,0 +1,732 @@
/*
* Copyright (c) 1999-2003 Damien Miller. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DEFINES_H
#define _DEFINES_H
/* $Id: defines.h,v 1.146 2008/02/28 08:22:04 dtucker Exp $ */
/* Constants */
#if defined(HAVE_DECL_SHUT_RD) && HAVE_DECL_SHUT_RD == 0
enum
{
SHUT_RD = 0, /* No more receptions. */
SHUT_WR, /* No more transmissions. */
SHUT_RDWR /* No more receptions or transmissions. */
};
# define SHUT_RD SHUT_RD
# define SHUT_WR SHUT_WR
# define SHUT_RDWR SHUT_RDWR
#endif
#ifndef IPTOS_LOWDELAY
# define IPTOS_LOWDELAY 0x10
# define IPTOS_THROUGHPUT 0x08
# define IPTOS_RELIABILITY 0x04
# define IPTOS_LOWCOST 0x02
# define IPTOS_MINCOST IPTOS_LOWCOST
#endif /* IPTOS_LOWDELAY */
#ifndef MAXPATHLEN
# ifdef PATH_MAX
# define MAXPATHLEN PATH_MAX
# else /* PATH_MAX */
# define MAXPATHLEN 64
/* realpath uses a fixed buffer of size MAXPATHLEN, so force use of ours */
# ifndef BROKEN_REALPATH
# define BROKEN_REALPATH 1
# endif /* BROKEN_REALPATH */
# endif /* PATH_MAX */
#endif /* MAXPATHLEN */
#ifndef PATH_MAX
# ifdef _POSIX_PATH_MAX
# define PATH_MAX _POSIX_PATH_MAX
# endif
#endif
#if defined(HAVE_DECL_MAXSYMLINKS) && HAVE_DECL_MAXSYMLINKS == 0
# define MAXSYMLINKS 5
#endif
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
# define STDERR_FILENO 2
#endif
#ifndef NGROUPS_MAX /* Disable groupaccess if NGROUP_MAX is not set */
#ifdef NGROUPS
#define NGROUPS_MAX NGROUPS
#else
#define NGROUPS_MAX 0
#endif
#endif
#if defined(HAVE_DECL_O_NONBLOCK) && HAVE_DECL_O_NONBLOCK == 0
# define O_NONBLOCK 00004 /* Non Blocking Open */
#endif
#ifndef S_ISDIR
# define S_ISDIR(mode) (((mode) & (_S_IFMT)) == (_S_IFDIR))
#endif /* S_ISDIR */
#ifndef S_ISREG
# define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG))
#endif /* S_ISREG */
#ifndef S_ISLNK
# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#endif /* S_ISLNK */
#ifndef S_IXUSR
# define S_IXUSR 0000100 /* execute/search permission, */
# define S_IXGRP 0000010 /* execute/search permission, */
# define S_IXOTH 0000001 /* execute/search permission, */
# define _S_IWUSR 0000200 /* write permission, */
# define S_IWUSR _S_IWUSR /* write permission, owner */
# define S_IWGRP 0000020 /* write permission, group */
# define S_IWOTH 0000002 /* write permission, other */
# define S_IRUSR 0000400 /* read permission, owner */
# define S_IRGRP 0000040 /* read permission, group */
# define S_IROTH 0000004 /* read permission, other */
# define S_IRWXU 0000700 /* read, write, execute */
# define S_IRWXG 0000070 /* read, write, execute */
# define S_IRWXO 0000007 /* read, write, execute */
#endif /* S_IXUSR */
#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
#define MAP_ANON MAP_ANONYMOUS
#endif
#ifndef MAP_FAILED
# define MAP_FAILED ((void *)-1)
#endif
/* *-*-nto-qnx doesn't define this constant in the system headers */
#ifdef MISSING_NFDBITS
# define NFDBITS (8 * sizeof(unsigned long))
#endif
/*
SCO Open Server 3 has INADDR_LOOPBACK defined in rpc/rpc.h but
including rpc/rpc.h breaks Solaris 6
*/
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK ((u_long)0x7f000001)
#endif
/* Types */
/* If sys/types.h does not supply intXX_t, supply them ourselves */
/* (or die trying) */
#ifndef HAVE_U_INT
typedef unsigned int u_int;
#endif
#ifndef HAVE_INTXX_T
# if (SIZEOF_CHAR == 1)
typedef char int8_t;
# else
# error "8 bit int type not found."
# endif
# if (SIZEOF_SHORT_INT == 2)
typedef short int int16_t;
# else
# ifdef _UNICOS
# if (SIZEOF_SHORT_INT == 4)
typedef short int16_t;
# else
typedef long int16_t;
# endif
# else
# error "16 bit int type not found."
# endif /* _UNICOS */
# endif
# if (SIZEOF_INT == 4)
typedef int int32_t;
# else
# ifdef _UNICOS
typedef long int32_t;
# else
# error "32 bit int type not found."
# endif /* _UNICOS */
# endif
#endif
/* If sys/types.h does not supply u_intXX_t, supply them ourselves */
#ifndef HAVE_U_INTXX_T
# ifdef HAVE_UINTXX_T
typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
# define HAVE_U_INTXX_T 1
# else
# if (SIZEOF_CHAR == 1)
typedef unsigned char u_int8_t;
# else
# error "8 bit int type not found."
# endif
# if (SIZEOF_SHORT_INT == 2)
typedef unsigned short int u_int16_t;
# else
# ifdef _UNICOS
# if (SIZEOF_SHORT_INT == 4)
typedef unsigned short u_int16_t;
# else
typedef unsigned long u_int16_t;
# endif
# else
# error "16 bit int type not found."
# endif
# endif
# if (SIZEOF_INT == 4)
typedef unsigned int u_int32_t;
# else
# ifdef _UNICOS
typedef unsigned long u_int32_t;
# else
# error "32 bit int type not found."
# endif
# endif
# endif
#define __BIT_TYPES_DEFINED__
#endif
/* 64-bit types */
#ifndef HAVE_INT64_T
# if (SIZEOF_LONG_INT == 8)
typedef long int int64_t;
# else
# if (SIZEOF_LONG_LONG_INT == 8)
typedef long long int int64_t;
# endif
# endif
#endif
#ifndef HAVE_U_INT64_T
# if (SIZEOF_LONG_INT == 8)
typedef unsigned long int u_int64_t;
# else
# if (SIZEOF_LONG_LONG_INT == 8)
typedef unsigned long long int u_int64_t;
# endif
# endif
#endif
#ifndef HAVE_U_CHAR
typedef unsigned char u_char;
# define HAVE_U_CHAR
#endif /* HAVE_U_CHAR */
#ifndef SIZE_T_MAX
#define SIZE_T_MAX ULONG_MAX
#endif /* SIZE_T_MAX */
#ifndef HAVE_SIZE_T
typedef unsigned int size_t;
# define HAVE_SIZE_T
# define SIZE_T_MAX UINT_MAX
#endif /* HAVE_SIZE_T */
#ifndef HAVE_SSIZE_T
typedef int ssize_t;
# define HAVE_SSIZE_T
#endif /* HAVE_SSIZE_T */
#ifndef HAVE_CLOCK_T
typedef long clock_t;
# define HAVE_CLOCK_T
#endif /* HAVE_CLOCK_T */
#ifndef HAVE_SA_FAMILY_T
typedef int sa_family_t;
# define HAVE_SA_FAMILY_T
#endif /* HAVE_SA_FAMILY_T */
#ifndef HAVE_PID_T
typedef int pid_t;
# define HAVE_PID_T
#endif /* HAVE_PID_T */
#ifndef HAVE_SIG_ATOMIC_T
typedef int sig_atomic_t;
# define HAVE_SIG_ATOMIC_T
#endif /* HAVE_SIG_ATOMIC_T */
#ifndef HAVE_MODE_T
typedef int mode_t;
# define HAVE_MODE_T
#endif /* HAVE_MODE_T */
#if !defined(HAVE_SS_FAMILY_IN_SS) && defined(HAVE___SS_FAMILY_IN_SS)
# define ss_family __ss_family
#endif /* !defined(HAVE_SS_FAMILY_IN_SS) && defined(HAVE_SA_FAMILY_IN_SS) */
#ifndef HAVE_SYS_UN_H
struct sockaddr_un {
short sun_family; /* AF_UNIX */
char sun_path[108]; /* path name (gag) */
};
#endif /* HAVE_SYS_UN_H */
#ifndef HAVE_IN_ADDR_T
typedef u_int32_t in_addr_t;
#endif
#if defined(BROKEN_SYS_TERMIO_H) && !defined(_STRUCT_WINSIZE)
#define _STRUCT_WINSIZE
struct winsize {
unsigned short ws_row; /* rows, in characters */
unsigned short ws_col; /* columns, in character */
unsigned short ws_xpixel; /* horizontal size, pixels */
unsigned short ws_ypixel; /* vertical size, pixels */
};
#endif
/* *-*-nto-qnx does not define this type in the system headers */
#ifdef MISSING_FD_MASK
typedef unsigned long int fd_mask;
#endif
/* Paths */
#ifndef _PATH_BSHELL
# define _PATH_BSHELL "/bin/sh"
#endif
#ifdef USER_PATH
# ifdef _PATH_STDPATH
# undef _PATH_STDPATH
# endif
# define _PATH_STDPATH USER_PATH
#endif
#ifndef _PATH_STDPATH
# define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
#endif
#ifndef SUPERUSER_PATH
# define SUPERUSER_PATH _PATH_STDPATH
#endif
#ifndef _PATH_DEVNULL
# define _PATH_DEVNULL "/dev/null"
#endif
#ifndef MAIL_DIRECTORY
# define MAIL_DIRECTORY "/var/spool/mail"
#endif
#ifndef MAILDIR
# define MAILDIR MAIL_DIRECTORY
#endif
#if !defined(_PATH_MAILDIR) && defined(MAILDIR)
# define _PATH_MAILDIR MAILDIR
#endif /* !defined(_PATH_MAILDIR) && defined(MAILDIR) */
#ifndef _PATH_NOLOGIN
# define _PATH_NOLOGIN "/etc/nologin"
#endif
/* Define this to be the path of the xauth program. */
#ifdef XAUTH_PATH
#define _PATH_XAUTH XAUTH_PATH
#endif /* XAUTH_PATH */
/* derived from XF4/xc/lib/dps/Xlibnet.h */
#ifndef X_UNIX_PATH
# ifdef __hpux
# define X_UNIX_PATH "/var/spool/sockets/X11/%u"
# else
# define X_UNIX_PATH "/tmp/.X11-unix/X%u"
# endif
#endif /* X_UNIX_PATH */
#define _PATH_UNIX_X X_UNIX_PATH
#ifndef _PATH_TTY
# define _PATH_TTY "/dev/tty"
#endif
/* Macros */
#if defined(HAVE_LOGIN_GETCAPBOOL) && defined(HAVE_LOGIN_CAP_H)
# define HAVE_LOGIN_CAP
#endif
#ifndef MAX
# define MAX(a,b) (((a)>(b))?(a):(b))
# define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef roundup
# define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
#endif
#ifndef timersub
#define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
#endif
#ifndef TIMEVAL_TO_TIMESPEC
#define TIMEVAL_TO_TIMESPEC(tv, ts) { \
(ts)->tv_sec = (tv)->tv_sec; \
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
}
#endif
#ifndef TIMESPEC_TO_TIMEVAL
#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
}
#endif
#ifndef __P
# define __P(x) x
#endif
#if !defined(IN6_IS_ADDR_V4MAPPED)
# define IN6_IS_ADDR_V4MAPPED(a) \
((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \
(((u_int32_t *) (a))[2] == htonl (0xffff)))
#endif /* !defined(IN6_IS_ADDR_V4MAPPED) */
#if !defined(__GNUC__) || (__GNUC__ < 2)
# define __attribute__(x)
#endif /* !defined(__GNUC__) || (__GNUC__ < 2) */
#ifndef __dead
# define __dead __attribute__((noreturn))
#endif
#if !defined(HAVE_ATTRIBUTE__SENTINEL__) && !defined(__sentinel__)
# define __sentinel__
#endif
#if !defined(HAVE_ATTRIBUTE__BOUNDED__) && !defined(__bounded__)
# define __bounded__(x, y, z)
#endif
#if !defined(HAVE_ATTRIBUTE__NONNULL__) && !defined(__nonnull__)
# define __nonnull__(x)
#endif
/* *-*-nto-qnx doesn't define this macro in the system headers */
#ifdef MISSING_HOWMANY
# define howmany(x,y) (((x)+((y)-1))/(y))
#endif
#ifndef OSSH_ALIGNBYTES
#define OSSH_ALIGNBYTES (sizeof(int) - 1)
#endif
#ifndef __CMSG_ALIGN
#define __CMSG_ALIGN(p) (((u_int)(p) + OSSH_ALIGNBYTES) &~ OSSH_ALIGNBYTES)
#endif
/* Length of the contents of a control message of length len */
#ifndef CMSG_LEN
#define CMSG_LEN(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
#endif
/* Length of the space taken up by a padded control message of length len */
#ifndef CMSG_SPACE
#define CMSG_SPACE(len) (__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(len))
#endif
/* given pointer to struct cmsghdr, return pointer to data */
#ifndef CMSG_DATA
#define CMSG_DATA(cmsg) ((u_char *)(cmsg) + __CMSG_ALIGN(sizeof(struct cmsghdr)))
#endif /* CMSG_DATA */
/*
* RFC 2292 requires to check msg_controllen, in case that the kernel returns
* an empty list for some reasons.
*/
#ifndef CMSG_FIRSTHDR
#define CMSG_FIRSTHDR(mhdr) \
((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \
(struct cmsghdr *)(mhdr)->msg_control : \
(struct cmsghdr *)NULL)
#endif /* CMSG_FIRSTHDR */
#if defined(HAVE_DECL_OFFSETOF) && HAVE_DECL_OFFSETOF == 0
# define offsetof(type, member) ((size_t) &((type *)0)->member)
#endif
/* Set up BSD-style BYTE_ORDER definition if it isn't there already */
/* XXX: doesn't try to cope with strange byte orders (PDP_ENDIAN) */
#ifndef BYTE_ORDER
# ifndef LITTLE_ENDIAN
# define LITTLE_ENDIAN 1234
# endif /* LITTLE_ENDIAN */
# ifndef BIG_ENDIAN
# define BIG_ENDIAN 4321
# endif /* BIG_ENDIAN */
# ifdef WORDS_BIGENDIAN
# define BYTE_ORDER BIG_ENDIAN
# else /* WORDS_BIGENDIAN */
# define BYTE_ORDER LITTLE_ENDIAN
# endif /* WORDS_BIGENDIAN */
#endif /* BYTE_ORDER */
/* Function replacement / compatibility hacks */
#if !defined(HAVE_GETADDRINFO) && (defined(HAVE_OGETADDRINFO) || defined(HAVE_NGETADDRINFO))
# define HAVE_GETADDRINFO
#endif
#ifndef HAVE_GETOPT_OPTRESET
# undef getopt
# undef opterr
# undef optind
# undef optopt
# undef optreset
# undef optarg
# define getopt(ac, av, o) BSDgetopt(ac, av, o)
# define opterr BSDopterr
# define optind BSDoptind
# define optopt BSDoptopt
# define optreset BSDoptreset
# define optarg BSDoptarg
#endif
#if defined(BROKEN_GETADDRINFO) && defined(HAVE_GETADDRINFO)
# undef HAVE_GETADDRINFO
#endif
#if defined(BROKEN_GETADDRINFO) && defined(HAVE_FREEADDRINFO)
# undef HAVE_FREEADDRINFO
#endif
#if defined(BROKEN_GETADDRINFO) && defined(HAVE_GAI_STRERROR)
# undef HAVE_GAI_STRERROR
#endif
#if defined(BROKEN_UPDWTMPX) && defined(HAVE_UPDWTMPX)
# undef HAVE_UPDWTMPX
#endif
#if defined(BROKEN_SHADOW_EXPIRE) && defined(HAS_SHADOW_EXPIRE)
# undef HAS_SHADOW_EXPIRE
#endif
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) && \
defined(SYSLOG_R_SAFE_IN_SIGHAND)
# define DO_LOG_SAFE_IN_SIGHAND
#endif
#if !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY)
# define memmove(s1, s2, n) bcopy((s2), (s1), (n))
#endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */
#if defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX)
# define USE_VHANGUP
#endif /* defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX) */
#ifndef GETPGRP_VOID
# include <unistd.h>
# define getpgrp() getpgrp(0)
#endif
#ifdef USE_BSM_AUDIT
# define SSH_AUDIT_EVENTS
# define CUSTOM_SSH_AUDIT_EVENTS
#endif
#if !defined(HAVE___func__) && defined(HAVE___FUNCTION__)
# define __func__ __FUNCTION__
#elif !defined(HAVE___func__)
# define __func__ ""
#endif
#if defined(KRB5) && !defined(HEIMDAL)
# define krb5_get_err_text(context,code) error_message(code)
#endif
#if defined(SKEYCHALLENGE_4ARG)
# define _compat_skeychallenge(a,b,c,d) skeychallenge(a,b,c,d)
#else
# define _compat_skeychallenge(a,b,c,d) skeychallenge(a,b,c)
#endif
/* Maximum number of file descriptors available */
#ifdef HAVE_SYSCONF
# define SSH_SYSFDMAX sysconf(_SC_OPEN_MAX)
#else
# define SSH_SYSFDMAX 10000
#endif
#if defined(__Lynx__)
/*
* LynxOS defines these in param.h which we do not want to include since
* it will also pull in a bunch of kernel definitions.
*/
# define ALIGNBYTES (sizeof(int) - 1)
# define ALIGN(p) (((unsigned)p + ALIGNBYTES) & ~ALIGNBYTES)
/* Missing prototypes on LynxOS */
int snprintf (char *, size_t, const char *, ...);
int mkstemp (char *);
char *crypt (const char *, const char *);
int seteuid (uid_t);
int setegid (gid_t);
char *mkdtemp (char *);
int rresvport_af (int *, sa_family_t);
int innetgr (const char *, const char *, const char *, const char *);
#endif
/*
* Define this to use pipes instead of socketpairs for communicating with the
* client program. Socketpairs do not seem to work on all systems.
*
* configure.ac sets this for a few OS's which are known to have problems
* but you may need to set it yourself
*/
/* #define USE_PIPES 1 */
/**
** login recorder definitions
**/
/* FIXME: put default paths back in */
#ifndef UTMP_FILE
# ifdef _PATH_UTMP
# define UTMP_FILE _PATH_UTMP
# else
# ifdef CONF_UTMP_FILE
# define UTMP_FILE CONF_UTMP_FILE
# endif
# endif
#endif
#ifndef WTMP_FILE
# ifdef _PATH_WTMP
# define WTMP_FILE _PATH_WTMP
# else
# ifdef CONF_WTMP_FILE
# define WTMP_FILE CONF_WTMP_FILE
# endif
# endif
#endif
/* pick up the user's location for lastlog if given */
#ifndef LASTLOG_FILE
# ifdef _PATH_LASTLOG
# define LASTLOG_FILE _PATH_LASTLOG
# else
# ifdef CONF_LASTLOG_FILE
# define LASTLOG_FILE CONF_LASTLOG_FILE
# endif
# endif
#endif
#if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW)
# define USE_SHADOW
#endif
/* The login() library function in libutil is first choice */
#if defined(HAVE_LOGIN) && !defined(DISABLE_LOGIN)
# define USE_LOGIN
#else
/* Simply select your favourite login types. */
/* Can't do if-else because some systems use several... <sigh> */
# if defined(UTMPX_FILE) && !defined(DISABLE_UTMPX)
# define USE_UTMPX
# endif
# if defined(UTMP_FILE) && !defined(DISABLE_UTMP)
# define USE_UTMP
# endif
# if defined(WTMPX_FILE) && !defined(DISABLE_WTMPX)
# define USE_WTMPX
# endif
# if defined(WTMP_FILE) && !defined(DISABLE_WTMP)
# define USE_WTMP
# endif
#endif
#ifndef UT_LINESIZE
# define UT_LINESIZE 8
#endif
/* I hope that the presence of LASTLOG_FILE is enough to detect this */
#if defined(LASTLOG_FILE) && !defined(DISABLE_LASTLOG)
# define USE_LASTLOG
#endif
#ifdef HAVE_OSF_SIA
# ifdef USE_SHADOW
# undef USE_SHADOW
# endif
# define CUSTOM_SYS_AUTH_PASSWD 1
#endif
#if defined(HAVE_LIBIAF) && defined(HAVE_SET_ID)
# define CUSTOM_SYS_AUTH_PASSWD 1
#endif
#if defined(HAVE_LIBIAF) && defined(HAVE_SET_ID) && !defined(BROKEN_LIBIAF)
# define USE_LIBIAF
#endif
/* HP-UX 11.11 */
#ifdef BTMP_FILE
# define _PATH_BTMP BTMP_FILE
#endif
#if defined(USE_BTMP) && defined(_PATH_BTMP)
# define CUSTOM_FAILED_LOGIN
#endif
/** end of login recorder definitions */
#ifdef BROKEN_GETGROUPS
# define getgroups(a,b) ((a)==0 && (b)==NULL ? NGROUPS_MAX : getgroups((a),(b)))
#endif
#if defined(HAVE_MMAP) && defined(BROKEN_MMAP)
# undef HAVE_MMAP
#endif
#ifndef IOV_MAX
# if defined(_XOPEN_IOV_MAX)
# define IOV_MAX _XOPEN_IOV_MAX
# elif defined(DEF_IOV_MAX)
# define IOV_MAX DEF_IOV_MAX
# else
# define IOV_MAX 16
# endif
#endif
#endif /* _DEFINES_H */

24
dist/LICENSE vendored Normal file
View File

@ -0,0 +1,24 @@
/*
* All distribution files are
* Copyright (c) 2010 Jamie Beverly. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/

102
dist/fedora/pam_ssh_agent_auth.spec vendored Normal file
View File

@ -0,0 +1,102 @@
Summary: PAM module providing authentication via ssh-agent
Name: pam_ssh_agent_auth
Version: 0.10.2
Release: 1%{?dist}
License: BSD
Group: System Environment Base
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(id -un)-root
Source0: http://downloads.sourceforge.net/pamsshagentauth/%{name}-%{version}.tar.bz2
Requires: openssl >= 0.9.8, pam, openssh-server, openssh
BuildRequires: openssl-devel >= 0.9.8, pam-devel, perl, sed
Vendor: Jamie Beverly
Packager: Jamie Beverly
%description
pam_ssh_agent_auth is a PAM module which permits PAM authentication via your
keyring in a forwarded ssh-agent.
Release 0.10.2 is stable, and has been tested on FreeBSD, Solaris 10, Solaris 11,
RHEL5, RHEL6, Debian Wheezy, Ubuntu 12.04 (LTS), Ubuntu 13.10,
and MacOS X 10.7.
This module can be used to provide authentication for anything run locally that
supports PAM. It was written specifically with the intention of permitting
authentication for sudo without password entry, and also has been proven useful
for use with su as an alternative to wheel.
It serves as middle ground between the two most common, and suboptimal
alternatives for large-scale system administration: allowing rootlogin via ssh,
or using NOPASSWD in sudoers. This module allows for ssh public-key
authentication, and it does this by leveraging an authentication mechanism you
are probably already using, ssh-agent.
There are caveats of course, ssh-agent forwarding has its own security risks
which must be carefully considered for your environment. In cases where there
are not untrustworthy intermediate servers, and you wish to retain traceability,
accountability, and required authentication for privileged command invocation,
the benefits should outweigh the risks. Release 0.10.2 can be downloaded from
SourceForge: https://sourceforge.net/project/showfiles.php?group_id=249556
If you encounter any issues with usability or security, please use the project's
SourceForge tracker:
https://sourceforge.net/tracker2/?group_id=249556&atid=1126337
Note that if you wish to use this for sudo, you will need a version of sudo that
preserves the env_keep environment during authentication; and ideally a version
incorporating my minor patch which ensures RUSER is set during PAM authentication.
sudo 1.6.8p12 does not work correctly with this PAM module, because it clears the
environment (even env_keep variables) prior to attempting PAM authentication.
sudo 1.7.2p1 or later is preferred, as it correctly sets PAM_RUSER for
authentication.
%clean
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
%prep
%setup
%build
%define _libexecdir /%{_lib}/security
%configure --with-selinux --enable-sudo-hack
%{__make} %{?_smp_mflags}
%install
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
%makeinstall
%files
%attr(0755, root, root) %{_libexecdir}/pam_ssh_agent_auth.so
%defattr(-, root, root, 0644)
%doc LICENSE.OpenSSL OPENSSH_LICENSE
%doc %{_mandir}/man8/pam_ssh_agent_auth.8*
%changelog
* Wed Mar 26 2014 Jamie Beverly <soupboy@sourceforge.net> - 0.10.2
- fix autoconf to work with autoreconf -fi
- correct sudo-version note in man page
- fix wire-protocol issue if a call fails
- add licensing information to files missing it
- correct licensing in debian files
- fix compiler warnings with -D_FORTIFY_SOURCE=2
- fix compiler warnings with -Wunused-parameter
* Thu Jan 9 2014 Jamie Beverly <soupboy@sourceforge.net> - 0.10.1
- Added support for authorized_keys_command and authorized_keys_command_user
* Sun 22 Sep 2013 Jamie Beverly <soupboy@sourceforge.net> - 0.9.6
- Fixed moderate security issue where the random cookie would rarely
be generated with zero length, creating an easily replayable authentication.
- Added metadata embedded in the information sent to ssh-agent, allowing agents
to present the user with more information about the authentication request,
so their decision to authorize the request can be an informed one.
* Thu Feb 21 2013 Jamie Beverly <soupboy@sourceforge.net> - 0.9.5
- portability fixes
* Wed Jun 26 2012 Jamie Beverly <soupboy@sourceforge.net> - 0.9.4
- Prefixed symbol names to avoid collision with globally dl_open'd symbols names
- updated Makefile.in as per http://sourceforge.net/tracker/?func=detail&aid=3510464&group_id=249556&atid=1126337
- updated documentation for pam configuration
* Wed Jan 26 2011 Jamie Beverly <jamie.r.beverly@gmail.com> - 0.9.3
- Minor bug fixes
- Moved logging of signature and key file from debug to normal output
* Wed Jan 06 2010 Jamie Beverly <jamie.r.beverly@gmail.com> - 0.9.2
- First packaged release.

View File

@ -0,0 +1,27 @@
# New ports collection makefile for: pam_ssh_agent_auth
# Date created: 18 January 2009
# Whom: Jamie Beverly
#
# $FreeBSD$
#
PORTNAME = pam_ssh_agent_auth
PORTVERSION = 0.10.2
CATEGORIES = security
MASTER_SITES = http://downloads.sourceforge.net/pamsshagentauth/pam_ssh_agent_auth-0.9.5.tar.bz2
EXTRACT_SUFX = .tar.bz2
WRKSRC = ${WRKDIR}/$(PORTNAME)
MAINTAINER = soupboy@sourceforge.net
COMMENT = A PAM module implementing authentication via ssh-agent
MAN8 = pam_ssh_agent_auth.8
MANCOMPRESSED = no
GNU_CONFIGURE = yes
USE_GMAKE = yes
PREFIX = /
MANPREFIX = /usr/share
CONFIGURE_ARGS = --libexecdir=/usr/lib --with-mantype=man
.include <bsd.port.mk>

View File

@ -0,0 +1,38 @@
pam_ssh_agent_auth is a PAM module which permits PAM authentication via your
keyring in a forwarded ssh-agent.
Release 0.10.2 is stable, and has been tested on FreeBSD, Solaris 10, Solaris 11,
RHEL5, RHEL6, Debian Wheezy, Ubuntu 12.04 (LTS), Ubuntu 13.10,
and MacOS X 10.7.
This module can be used to provide authentication for anything run locally that
supports PAM. It was written specifically with the intention of permitting
authentication for sudo without password entry, and also has been proven useful
for use with su as an alternative to wheel.
It serves as middle ground between the two most common, and suboptimal
alternatives for large-scale system administration: allowing rootlogin via ssh,
or using NOPASSWD in sudoers. This module allows for ssh public-key
authentication, and it does this by leveraging an authentication mechanism you
are probably already using, ssh-agent.
There are caveats of course, ssh-agent forwarding has its own security risks
which must be carefully considered for your environment. In cases where there
are not untrustworthy intermediate servers, and you wish to retain traceability,
accountability, and required authentication for privileged command invocation,
the benefits should outweigh the risks. Release 0.10.2 can be downloaded from
SourceForge: https://sourceforge.net/project/showfiles.php?group_id=249556
If you encounter any issues with usability or security, please use the project's
SourceForge tracker:
https://sourceforge.net/tracker2/?group_id=249556&atid=1126337
Note that if you wish to use this for sudo, you will need a version of sudo that
preserves the env_keep environment during authentication; and ideally a version
incorporating my minor patch which ensures RUSER is set during PAM authentication.
sudo 1.6.8p12 does not work correctly with this PAM module, because it clears the
environment (even env_keep variables) prior to attempting PAM authentication.
sudo 1.7.2p1 or later is preferred, as it correctly sets PAM_RUSER for
authentication.

View File

@ -0,0 +1 @@
/usr/lib/pam_ssh_agent_auth.so

102
dist/rhel4/pam_ssh_agent_auth.spec vendored Normal file
View File

@ -0,0 +1,102 @@
Summary: PAM module providing authentication via ssh-agent
Name: pam_ssh_agent_auth
Version: 0.10.2
Release: 1%{?dist}
License: BSD
Group: System Environment Base
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(id -un)-root
Source0: http://downloads.sourceforge.net/pamsshagentauth/%{name}-%{version}.tar.bz2
Requires: openssl >= 0.9.8, pam, openssh-server, openssh
BuildRequires: openssl-devel >= 0.9.8, pam-devel, perl, sed
Vendor: Jamie Beverly
Packager: Jamie Beverly
%description
pam_ssh_agent_auth is a PAM module which permits PAM authentication via your
keyring in a forwarded ssh-agent.
Release 0.10.2 is stable, and has been tested on FreeBSD, Solaris 10, Solaris 11,
RHEL5, RHEL6, Debian Wheezy, Ubuntu 12.04 (LTS), Ubuntu 13.10,
and MacOS X 10.7.
This module can be used to provide authentication for anything run locally that
supports PAM. It was written specifically with the intention of permitting
authentication for sudo without password entry, and also has been proven useful
for use with su as an alternative to wheel.
It serves as middle ground between the two most common, and suboptimal
alternatives for large-scale system administration: allowing rootlogin via ssh,
or using NOPASSWD in sudoers. This module allows for ssh public-key
authentication, and it does this by leveraging an authentication mechanism you
are probably already using, ssh-agent.
There are caveats of course, ssh-agent forwarding has its own security risks
which must be carefully considered for your environment. In cases where there
are not untrustworthy intermediate servers, and you wish to retain traceability,
accountability, and required authentication for privileged command invocation,
the benefits should outweigh the risks. Release 0.10.2 can be downloaded from
SourceForge: https://sourceforge.net/project/showfiles.php?group_id=249556
If you encounter any issues with usability or security, please use the project's
SourceForge tracker:
https://sourceforge.net/tracker2/?group_id=249556&atid=1126337
Note that if you wish to use this for sudo, you will need a version of sudo that
preserves the env_keep environment during authentication; and ideally a version
incorporating my minor patch which ensures RUSER is set during PAM authentication.
sudo 1.6.8p12 does not work correctly with this PAM module, because it clears the
environment (even env_keep variables) prior to attempting PAM authentication.
sudo 1.7.2p1 or later is preferred, as it correctly sets PAM_RUSER for
authentication.
%clean
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
%prep
%setup
%build
%define _libexecdir /%{_lib}/security
%configure --with-selinux --enable-sudo-hack
%{__make} %{?_smp_mflags}
%install
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
%makeinstall
%files
%attr(0755, root, root) %{_libexecdir}/pam_ssh_agent_auth.so
%defattr(-, root, root, 0644)
%doc LICENSE.OpenSSL OPENSSH_LICENSE
%doc %{_mandir}/man8/pam_ssh_agent_auth.8*
%changelog
* Wed Mar 26 2014 Jamie Beverly <soupboy@sourceforge.net> - 0.10.2
- fix autoconf to work with autoreconf -fi
- correct sudo-version note in man page
- fix wire-protocol issue if a call fails
- add licensing information to files missing it
- correct licensing in debian files
- fix compiler warnings with -D_FORTIFY_SOURCE=2
- fix compiler warnings with -Wunused-parameter
* Thu Jan 9 2014 Jamie Beverly <soupboy@sourceforge.net> - 0.10.1
- Added support for authorized_keys_command and authorized_keys_command_user
* Sun 22 Sep 2013 Jamie Beverly <soupboy@sourceforge.net> - 0.9.6
- Fixed moderate security issue where the random cookie would rarely
be generated with zero length, creating an easily replayable authentication.
- Added metadata embedded in the information sent to ssh-agent, allowing agents
to present the user with more information about the authentication request,
so their decision to authorize the request can be an informed one.
* Thu Feb 21 2013 Jamie Beverly <soupboy@sourceforge.net> - 0.9.5
- portability fixes
* Wed Jun 26 2012 Jamie Beverly <soupboy@sourceforge.net> - 0.9.4
- Prefixed symbol names to avoid collision with globally dl_open'd symbols names
- updated Makefile.in as per http://sourceforge.net/tracker/?func=detail&aid=3510464&group_id=249556&atid=1126337
- updated documentation for pam configuration
* Wed Jan 26 2011 Jamie Beverly <jamie.r.beverly@gmail.com> - 0.9.3
- Minor bug fixes
- Moved logging of signature and key file from debug to normal output
* Wed Jan 06 2010 Jamie Beverly <jamie.r.beverly@gmail.com> - 0.9.2
- First packaged release.

102
dist/rhel5/pam_ssh_agent_auth.spec vendored Normal file
View File

@ -0,0 +1,102 @@
Summary: PAM module providing authentication via ssh-agent
Name: pam_ssh_agent_auth
Version: 0.10.2
Release: 1%{?dist}
License: BSD
Group: System Environment Base
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(id -un)-root
Source0: http://downloads.sourceforge.net/pamsshagentauth/%{name}-%{version}.tar.bz2
Requires: openssl >= 0.9.8, pam, openssh-server, openssh
BuildRequires: openssl-devel >= 0.9.8, pam-devel, perl, sed
Vendor: Jamie Beverly
Packager: Jamie Beverly
%description
pam_ssh_agent_auth is a PAM module which permits PAM authentication via your
keyring in a forwarded ssh-agent.
Release 0.10.2 is stable, and has been tested on FreeBSD, Solaris 10, Solaris 11,
RHEL5, RHEL6, Debian Wheezy, Ubuntu 12.04 (LTS), Ubuntu 13.10,
and MacOS X 10.7.
This module can be used to provide authentication for anything run locally that
supports PAM. It was written specifically with the intention of permitting
authentication for sudo without password entry, and also has been proven useful
for use with su as an alternative to wheel.
It serves as middle ground between the two most common, and suboptimal
alternatives for large-scale system administration: allowing rootlogin via ssh,
or using NOPASSWD in sudoers. This module allows for ssh public-key
authentication, and it does this by leveraging an authentication mechanism you
are probably already using, ssh-agent.
There are caveats of course, ssh-agent forwarding has its own security risks
which must be carefully considered for your environment. In cases where there
are not untrustworthy intermediate servers, and you wish to retain traceability,
accountability, and required authentication for privileged command invocation,
the benefits should outweigh the risks. Release 0.10.2 can be downloaded from
SourceForge: https://sourceforge.net/project/showfiles.php?group_id=249556
If you encounter any issues with usability or security, please use the project's
SourceForge tracker:
https://sourceforge.net/tracker2/?group_id=249556&atid=1126337
Note that if you wish to use this for sudo, you will need a version of sudo that
preserves the env_keep environment during authentication; and ideally a version
incorporating my minor patch which ensures RUSER is set during PAM authentication.
sudo 1.6.8p12 does not work correctly with this PAM module, because it clears the
environment (even env_keep variables) prior to attempting PAM authentication.
sudo 1.7.2p1 or later is preferred, as it correctly sets PAM_RUSER for
authentication.
%clean
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
%prep
%setup
%build
%define _libexecdir /%{_lib}/security
%configure --with-selinux --enable-sudo-hack
%{__make} %{?_smp_mflags}
%install
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
%makeinstall
%files
%attr(0755, root, root) %{_libexecdir}/pam_ssh_agent_auth.so
%defattr(-, root, root, 0644)
%doc LICENSE.OpenSSL OPENSSH_LICENSE
%doc %{_mandir}/man8/pam_ssh_agent_auth.8*
%changelog
* Wed Mar 26 2014 Jamie Beverly <soupboy@sourceforge.net> - 0.10.2
- fix autoconf to work with autoreconf -fi
- correct sudo-version note in man page
- fix wire-protocol issue if a call fails
- add licensing information to files missing it
- correct licensing in debian files
- fix compiler warnings with -D_FORTIFY_SOURCE=2
- fix compiler warnings with -Wunused-parameter
* Thu Jan 9 2014 Jamie Beverly <soupboy@sourceforge.net> - 0.10.1
- Added support for authorized_keys_command and authorized_keys_command_user
* Sun 22 Sep 2013 Jamie Beverly <soupboy@sourceforge.net> - 0.9.6
- Fixed moderate security issue where the random cookie would rarely
be generated with zero length, creating an easily replayable authentication.
- Added metadata embedded in the information sent to ssh-agent, allowing agents
to present the user with more information about the authentication request,
so their decision to authorize the request can be an informed one.
* Thu Feb 21 2013 Jamie Beverly <soupboy@sourceforge.net> - 0.9.5
- portability fixes
* Wed Jun 26 2012 Jamie Beverly <soupboy@sourceforge.net> - 0.9.4
- Prefixed symbol names to avoid collision with globally dl_open'd symbols names
- updated Makefile.in as per http://sourceforge.net/tracker/?func=detail&aid=3510464&group_id=249556&atid=1126337
- updated documentation for pam configuration
* Wed Jan 26 2011 Jamie Beverly <jamie.r.beverly@gmail.com> - 0.9.3
- Minor bug fixes
- Moved logging of signature and key file from debug to normal output
* Wed Jan 06 2010 Jamie Beverly <jamie.r.beverly@gmail.com> - 0.9.2
- First packaged release.

102
dist/rhel6/pam_ssh_agent_auth.spec vendored Normal file
View File

@ -0,0 +1,102 @@
Summary: PAM module providing authentication via ssh-agent
Name: pam_ssh_agent_auth
Version: 0.10.2
Release: 1%{?dist}
License: BSD
Group: System Environment Base
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(id -un)-root
Source0: http://downloads.sourceforge.net/pamsshagentauth/%{name}-%{version}.tar.bz2
Requires: openssl >= 0.9.8, pam, openssh-server, openssh
BuildRequires: openssl-devel >= 0.9.8, pam-devel, perl, sed
Vendor: Jamie Beverly
Packager: Jamie Beverly
%description
pam_ssh_agent_auth is a PAM module which permits PAM authentication via your
keyring in a forwarded ssh-agent.
Release 0.10.2 is stable, and has been tested on FreeBSD, Solaris 10, Solaris 11,
RHEL5, RHEL6, Debian Wheezy, Ubuntu 12.04 (LTS), Ubuntu 13.10,
and MacOS X 10.7.
This module can be used to provide authentication for anything run locally that
supports PAM. It was written specifically with the intention of permitting
authentication for sudo without password entry, and also has been proven useful
for use with su as an alternative to wheel.
It serves as middle ground between the two most common, and suboptimal
alternatives for large-scale system administration: allowing rootlogin via ssh,
or using NOPASSWD in sudoers. This module allows for ssh public-key
authentication, and it does this by leveraging an authentication mechanism you
are probably already using, ssh-agent.
There are caveats of course, ssh-agent forwarding has its own security risks
which must be carefully considered for your environment. In cases where there
are not untrustworthy intermediate servers, and you wish to retain traceability,
accountability, and required authentication for privileged command invocation,
the benefits should outweigh the risks. Release 0.10.2 can be downloaded from
SourceForge: https://sourceforge.net/project/showfiles.php?group_id=249556
If you encounter any issues with usability or security, please use the project's
SourceForge tracker:
https://sourceforge.net/tracker2/?group_id=249556&atid=1126337
Note that if you wish to use this for sudo, you will need a version of sudo that
preserves the env_keep environment during authentication; and ideally a version
incorporating my minor patch which ensures RUSER is set during PAM authentication.
sudo 1.6.8p12 does not work correctly with this PAM module, because it clears the
environment (even env_keep variables) prior to attempting PAM authentication.
sudo 1.7.2p1 or later is preferred, as it correctly sets PAM_RUSER for
authentication.
%clean
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
%prep
%setup
%build
%define _libexecdir /%{_lib}/security
%configure --with-selinux --enable-sudo-hack
%{__make} %{?_smp_mflags}
%install
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
%makeinstall
%files
%attr(0755, root, root) %{_libexecdir}/pam_ssh_agent_auth.so
%defattr(-, root, root, 0644)
%doc LICENSE.OpenSSL OPENSSH_LICENSE
%doc %{_mandir}/man8/pam_ssh_agent_auth.8*
%changelog
* Wed Mar 26 2014 Jamie Beverly <soupboy@sourceforge.net> - 0.10.2
- fix autoconf to work with autoreconf -fi
- correct sudo-version note in man page
- fix wire-protocol issue if a call fails
- add licensing information to files missing it
- correct licensing in debian files
- fix compiler warnings with -D_FORTIFY_SOURCE=2
- fix compiler warnings with -Wunused-parameter
* Thu Jan 9 2014 Jamie Beverly <soupboy@sourceforge.net> - 0.10.1
- Added support for authorized_keys_command and authorized_keys_command_user
* Sun 22 Sep 2013 Jamie Beverly <soupboy@sourceforge.net> - 0.9.6
- Fixed moderate security issue where the random cookie would rarely
be generated with zero length, creating an easily replayable authentication.
- Added metadata embedded in the information sent to ssh-agent, allowing agents
to present the user with more information about the authentication request,
so their decision to authorize the request can be an informed one.
* Thu Feb 21 2013 Jamie Beverly <soupboy@sourceforge.net> - 0.9.5
- portability fixes
* Wed Jun 26 2012 Jamie Beverly <soupboy@sourceforge.net> - 0.9.4
- Prefixed symbol names to avoid collision with globally dl_open'd symbols names
- updated Makefile.in as per http://sourceforge.net/tracker/?func=detail&aid=3510464&group_id=249556&atid=1126337
- updated documentation for pam configuration
* Wed Jan 26 2011 Jamie Beverly <jamie.r.beverly@gmail.com> - 0.9.3
- Minor bug fixes
- Moved logging of signature and key file from debug to normal output
* Wed Jan 06 2010 Jamie Beverly <jamie.r.beverly@gmail.com> - 0.9.2
- First packaged release.

194
entropy.c Normal file
View File

@ -0,0 +1,194 @@
/*
* Copyright (c) 2001 Damien Miller. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "includes.h"
#include <sys/types.h>
#include <sys/wait.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#include <stdarg.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <openssl/rand.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include "ssh.h"
#include "misc.h"
#include "xmalloc.h"
#include "atomicio.h"
#include "pathnames.h"
#include "log.h"
#include "buffer.h"
/*
* Portable OpenSSH PRNG seeding:
* If OpenSSL has not "internally seeded" itself (e.g. pulled data from
* /dev/random), then we execute a "ssh-rand-helper" program which
* collects entropy and writes it to stdout. The child program must
* write at least RANDOM_SEED_SIZE bytes. The child is run with stderr
* attached, so error/verboseging output should be visible.
*
* XXX: we should tell the child how many bytes we need.
*/
#ifndef OPENSSL_PRNG_ONLY
#define RANDOM_SEED_SIZE 48
static uid_t original_uid, original_euid;
#endif
void
pamsshagentauth_seed_rng(void)
{
#ifndef OPENSSL_PRNG_ONLY
int devnull;
int p[2];
pid_t pid;
int ret;
unsigned char buf[RANDOM_SEED_SIZE];
mysig_t old_sigchld;
if (RAND_status() == 1) {
pamsshagentauth_verbose("RNG is ready, skipping seeding");
return;
}
pamsshagentauth_verbose("Seeding PRNG from %s", SSH_RAND_HELPER);
if ((devnull = open("/dev/null", O_RDWR)) == -1)
pamsshagentauth_fatal("Couldn't open /dev/null: %s", strerror(errno));
if (pipe(p) == -1)
pamsshagentauth_fatal("pipe: %s", strerror(errno));
old_sigchld = signal(SIGCHLD, SIG_DFL);
if ((pid = fork()) == -1)
pamsshagentauth_fatal("Couldn't fork: %s", strerror(errno));
if (pid == 0) {
dup2(devnull, STDIN_FILENO);
dup2(p[1], STDOUT_FILENO);
/* Keep stderr open for errors */
close(p[0]);
close(p[1]);
close(devnull);
if (original_uid != original_euid &&
( seteuid(getuid()) == -1 ||
setuid(original_uid) == -1) ) {
fprintf(stderr, "(rand child) setuid(%li): %s\n",
(long int)original_uid, strerror(errno));
_exit(1);
}
execl(SSH_RAND_HELPER, "ssh-rand-helper", NULL);
fprintf(stderr, "(rand child) Couldn't exec '%s': %s\n",
SSH_RAND_HELPER, strerror(errno));
_exit(1);
}
close(devnull);
close(p[1]);
memset(buf, '\0', sizeof(buf));
ret = pamsshagentauth_atomicio(read, p[0], buf, sizeof(buf));
if (ret == -1)
pamsshagentauth_fatal("Couldn't read from ssh-rand-helper: %s",
strerror(errno));
if (ret != sizeof(buf))
pamsshagentauth_fatal("ssh-rand-helper child produced insufficient data");
close(p[0]);
if (waitpid(pid, &ret, 0) == -1)
pamsshagentauth_fatal("Couldn't wait for ssh-rand-helper completion: %s",
strerror(errno));
signal(SIGCHLD, old_sigchld);
/* We don't mind if the child exits upon a SIGPIPE */
if (!WIFEXITED(ret) &&
(!WIFSIGNALED(ret) || WTERMSIG(ret) != SIGPIPE))
pamsshagentauth_fatal("ssh-rand-helper terminated abnormally");
if (WEXITSTATUS(ret) != 0)
pamsshagentauth_fatal("ssh-rand-helper exit with exit status %d", ret);
RAND_add(buf, sizeof(buf), sizeof(buf));
memset(buf, '\0', sizeof(buf));
#endif /* OPENSSL_PRNG_ONLY */
if (RAND_status() != 1)
pamsshagentauth_fatal("PRNG is not seeded");
}
void
pamsshagentauth_init_rng(void)
{
/*
* OpenSSL version numbers: MNNFFPPS: major minor fix patch status
* We match major, minor, fix and status (not patch)
*/
if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L)
pamsshagentauth_fatal("OpenSSL version mismatch. Built against %lx, you "
"have %lx", OPENSSL_VERSION_NUMBER, SSLeay());
#ifndef OPENSSL_PRNG_ONLY
original_uid = getuid();
original_euid = geteuid();
#endif
}
#ifndef OPENSSL_PRNG_ONLY
void
rexec_send_rng_seed(Buffer *m)
{
u_char buf[RANDOM_SEED_SIZE];
if (RAND_bytes(buf, sizeof(buf)) <= 0) {
pamsshagentauth_logerror("Couldn't obtain random bytes (error %ld)",
ERR_get_error());
pamsshagentauth_buffer_put_string(m, "", 0);
} else
pamsshagentauth_buffer_put_string(m, buf, sizeof(buf));
}
void
rexec_recv_rng_seed(Buffer *m)
{
u_char *buf;
u_int len;
buf = pamsshagentauth_buffer_get_string_ret(m, &len);
if (buf != NULL) {
pamsshagentauth_verbose("rexec_recv_rng_seed: seeding rng with %u bytes", len);
RAND_add(buf, len, len);
}
}
#endif

38
entropy.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 1999-2000 Damien Miller. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
/* $Id: entropy.h,v 1.5 2005/09/27 12:46:32 dtucker Exp $ */
#ifndef _RANDOMS_H
#define _RANDOMS_H
#include "buffer.h"
void pamsshagentauth_seed_rng(void);
void pamsshagentauth_init_rng(void);
void rexec_send_rng_seed(Buffer *);
void rexec_recv_rng_seed(Buffer *);
#endif /* _RANDOMS_H */

45
fatal.c Normal file
View File

@ -0,0 +1,45 @@
/* $OpenBSD: fatal.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "includes.h"
#include <sys/types.h>
#include <stdarg.h>
#include "log.h"
/* Fatal messages. This function never returns. */
void
pamsshagentauth_fatal(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
pamsshagentauth_do_log(SYSLOG_LEVEL_FATAL, fmt, args);
va_end(args);
pamsshagentauth_cleanup_exit(255);
}

113
get_command_line.c Normal file
View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2014, Jamie Beverly.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY Jamie Beverly ``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 Jamie Beverly 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 Jamie Beverly.
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "includes.h"
#include "xmalloc.h"
#include "get_command_line.h"
#ifdef HAVE_PROC_PID_CMDLINE
static size_t
proc_pid_cmdline(char *** inargv)
{
pid_t pid;
FILE *f = NULL;
char filename[64] = { 0 }, c = '\0';
char ** argv;
char argbuf[MAX_LEN_PER_CMDLINE_ARG + 1] = { 0 };
size_t count = 0, len = 0;
pid = getpid();
argv = NULL;
snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid);
f = fopen(filename, "r");
if (f) {
while (!feof(f) && count < MAX_CMDLINE_ARGS) {
if (len > MAX_LEN_PER_CMDLINE_ARG) {
while (!feof(f) && (c = fgetc(f)) != '\0');
}
else {
c = fgetc(f);
}
switch (c) {
case EOF:
case '\0':
if (len > 0) {
argv = pamsshagentauth_xrealloc(argv, count + 1, sizeof(*argv));
argv[count] = pamsshagentauth_xcalloc(len + 1, sizeof(*argv[count]));
strncpy(argv[count++], argbuf, len);
memset(argbuf, '\0', MAX_LEN_PER_CMDLINE_ARG + 1);
len = 0;
}
break;
default:
argbuf[len++] = c;
break;
}
}
fclose(f);
}
*inargv = argv;
return count;
}
#endif
/*
* takes a pointer to an unallocated array of arrays of strings, populates the
* given pointer with the address of the allocated array of strings collected
*/
size_t
pamsshagentauth_get_command_line(char *** argv)
{
#ifdef HAVE_PROC_PID_CMDLINE
return proc_pid_cmdline(argv);
#else
/* No other supported implementations at this time */
return 0;
#endif
}
void
pamsshagentauth_free_command_line(char ** argv, size_t n_args)
{
size_t i;
for (i = 0; i < n_args; i++)
pamsshagentauth_xfree(argv[i]);
pamsshagentauth_xfree(argv);
return;
}

40
get_command_line.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2014, Jamie Beverly.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY Jamie Beverly ``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 Jamie Beverly 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 Jamie Beverly.
*/
#ifndef _GET_COMMAND_LINE_H
#define _GET_COMMAND_LINE_H
#include "includes.h"
size_t pamsshagentauth_get_command_line(char ***);
void pamsshagentauth_free_command_line(char **, size_t);
#define MAX_CMDLINE_ARGS 255
#define MAX_LEN_PER_CMDLINE_ARG 255
#endif

50
identity.h Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2000 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _IDENTITY_H
#define _IDENTITY_H
#include "includes.h"
#include "config.h"
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "log.h"
#include "buffer.h"
#include "key.h"
#include "authfd.h"
#include <stdio.h>
typedef struct identity Identity;
typedef struct idlist Idlist;
struct identity {
TAILQ_ENTRY(identity) next;
AuthenticationConnection *ac; /* set if agent supports key */
Key *key; /* public/private key */
char *filename; /* comment for agent-only keys */
int tried;
int isprivate; /* key points to the private key */
};
TAILQ_HEAD(idlist, identity);
#endif

176
includes.h Normal file
View File

@ -0,0 +1,176 @@
/* $OpenBSD: includes.h,v 1.54 2006/07/22 20:48:23 stevesk Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* This file includes most of the needed system headers.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#ifndef INCLUDES_H
#define INCLUDES_H
#include "config.h"
#include <sys/types.h>
#include <sys/socket.h> /* For CMSG_* */
#ifdef HAVE_LIMITS_H
# include <limits.h> /* For PATH_MAX */
#endif
#ifdef HAVE_BSTRING_H
# include <bstring.h>
#endif
#if defined(HAVE_GLOB_H) && defined(GLOB_HAS_ALTDIRFUNC) && \
defined(GLOB_HAS_GL_MATCHC) && \
defined(HAVE_DECL_GLOB_NOMATCH) && HAVE_DECL_GLOB_NOMATCH != 0
# include <glob.h>
#endif
#ifdef HAVE_ENDIAN_H
# include <endian.h>
#endif
#ifdef HAVE_TTYENT_H
# include <ttyent.h>
#endif
#ifdef HAVE_UTIME_H
# include <utime.h>
#endif
#ifdef HAVE_TIME_H
# include <time.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_MAILLOCK_H
# include <maillock.h> /* For _PATH_MAILDIR */
#endif
#ifdef HAVE_NEXT
# include <libc.h>
#endif
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
/*
*-*-nto-qnx needs these headers for strcasecmp and LASTLOG_FILE respectively
*/
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_LOGIN_H
# include <login.h>
#endif
#ifdef HAVE_UTMP_H
# include <utmp.h>
#endif
#ifdef HAVE_UTMPX_H
# include <utmpx.h>
#endif
#ifdef HAVE_LASTLOG_H
# include <lastlog.h>
#endif
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#ifdef HAVE_SYS_BSDTTY_H
# include <sys/bsdtty.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <termios.h>
#ifdef HAVE_SYS_BITYPES_H
# include <sys/bitypes.h> /* For u_intXX_t */
#endif
#ifdef HAVE_SYS_CDEFS_H
# include <sys/cdefs.h> /* For __P() */
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h> /* For S_* constants and macros */
#endif
#ifdef HAVE_SYS_SYSMACROS_H
# include <sys/sysmacros.h> /* For MIN, MAX, etc */
#endif
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h> /* for MAP_ANONYMOUS */
#endif
#ifdef HAVE_SYS_STRTIO_H
#include <sys/strtio.h> /* for TIOCCBRK on HP-UX */
#endif
#if defined(HAVE_SYS_PTMS_H) && defined(HAVE_DEV_PTMX)
# if defined(HAVE_SYS_STREAM_H)
# include <sys/stream.h> /* reqd for queue_t on Solaris 2.5.1 */
# endif
#include <sys/ptms.h> /* for grantpt() and friends */
#endif
#include <netinet/in.h>
#include <netinet/in_systm.h> /* For typedefs */
#ifdef HAVE_RPC_TYPES_H
# include <rpc/types.h> /* For INADDR_LOOPBACK */
#endif
#ifdef USE_PAM
#if defined(HAVE_SECURITY_PAM_APPL_H)
# include <security/pam_appl.h>
#elif defined (HAVE_PAM_PAM_APPL_H)
# include <pam/pam_appl.h>
#endif
#endif
#ifdef HAVE_READPASSPHRASE_H
# include <readpassphrase.h>
#endif
#ifdef HAVE_IA_H
# include <ia.h>
#endif
#ifdef HAVE_IAF_H
# include <iaf.h>
#endif
#ifdef HAVE_TMPDIR_H
# include <tmpdir.h>
#endif
#ifdef HAVE_LIBUTIL_H
# include <libutil.h> /* Openpty on FreeBSD at least */
#endif
#if defined(KRB5) && defined(USE_AFS)
# include <krb5.h>
# include <kafs.h>
#endif
#if defined(HAVE_SYS_SYSLOG_H)
# include <sys/syslog.h>
#endif
/*
* On HP-UX 11.11, shadow.h and prot.h provide conflicting declarations
* of getspnam when _INCLUDE__STDC__ is defined, so we unset it here.
*/
#ifdef GETSPNAM_CONFLICTING_DEFS
# ifdef _INCLUDE__STDC__
# undef _INCLUDE__STDC__
# endif
#endif
#include <openssl/opensslv.h> /* For OPENSSL_VERSION_NUMBER */
#include "defines.h"
#include "platform.h"
#include "openbsd-compat/openbsd-compat.h"
#include "openbsd-compat/bsd-nextstep.h"
#include "entropy.h"
#endif /* INCLUDES_H */

251
install-sh Executable file
View File

@ -0,0 +1,251 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# 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. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# 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}"
transformbasename=""
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=:
chmodcmd=""
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

221
iterate_ssh_agent_keys.c Normal file
View File

@ -0,0 +1,221 @@
/*
* Copyright (c) 2008, Jamie Beverly.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY Jamie Beverly ``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 Jamie Beverly 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 Jamie Beverly.
*/
#include <string.h>
#include "includes.h"
#include "config.h"
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "log.h"
#include "buffer.h"
#include "key.h"
#include "authfd.h"
#include <stdio.h>
#include <openssl/evp.h>
#include "ssh2.h"
#include "misc.h"
#include "userauth_pubkey_from_id.h"
#include "identity.h"
#include "get_command_line.h"
extern char **environ;
static char *
log_action(char ** action, size_t count)
{
size_t i;
char *buf = NULL;
if (count == 0)
return NULL;
buf = pamsshagentauth_xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf));
for (i = 0; i < count; i++) {
strcat(buf, (i > 0) ? " '" : "'");
strncat(buf, action[i], MAX_LEN_PER_CMDLINE_ARG);
strcat(buf, "'");
}
return buf;
}
void
agent_action(Buffer *buf, char ** action, size_t count)
{
size_t i;
pamsshagentauth_buffer_init(buf);
pamsshagentauth_buffer_put_int(buf, count);
for (i = 0; i < count; i++) {
pamsshagentauth_buffer_put_cstring(buf, action[i]);
}
}
void
pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user,
const char * ruser, const char * servicename)
{
char *cookie = NULL;
uint8_t i = 0;
uint32_t rnd = 0;
uint8_t cookie_len;
char hostname[256] = { 0 };
char pwd[1024] = { 0 };
time_t ts;
char ** reported_argv = NULL;
size_t count = 0;
char * action_logbuf = NULL;
Buffer action_agentbuf;
uint8_t free_logbuf = 0;
char * retc;
int32_t reti;
rnd = pamsshagentauth_arc4random();
cookie_len = ((uint8_t) rnd);
while (cookie_len < 16) {
cookie_len += 16; /* Add 16 bytes to the size to ensure that while the length is random, the length is always reasonable; ticket #18 */
}
cookie = pamsshagentauth_xcalloc(1,cookie_len);
for (i = 0; i < cookie_len; i++) {
if (i % 4 == 0) {
rnd = pamsshagentauth_arc4random();
}
cookie[i] = (char) rnd;
rnd >>= 8;
}
count = pamsshagentauth_get_command_line(&reported_argv);
if (count > 0) {
free_logbuf = 1;
action_logbuf = log_action(reported_argv, count);
agent_action(&action_agentbuf, reported_argv, count);
pamsshagentauth_free_command_line(reported_argv, count);
}
else {
action_logbuf = "unknown on this platform";
pamsshagentauth_buffer_init(&action_agentbuf); /* stays empty, means unavailable */
}
/*
action = getenv("SUDO_COMMAND");
if(!action) {
action = getenv("PAM_AUTHORIZED_ACTION");
if(!action) {
action = empty;
}
}
*/
reti = gethostname(hostname, sizeof(hostname) - 1);
retc = getcwd(pwd, sizeof(pwd) - 1);
time(&ts);
pamsshagentauth_buffer_init(session_id2);
pamsshagentauth_buffer_put_int(session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1);
/* pamsshagentauth_debug3("cookie: %s", pamsshagentauth_tohex(cookie, cookie_len)); */
pamsshagentauth_buffer_put_string(session_id2, cookie, cookie_len);
/* pamsshagentauth_debug3("user: %s", user); */
pamsshagentauth_buffer_put_cstring(session_id2, user);
/* pamsshagentauth_debug3("ruser: %s", ruser); */
pamsshagentauth_buffer_put_cstring(session_id2, ruser);
/* pamsshagentauth_debug3("servicename: %s", servicename); */
pamsshagentauth_buffer_put_cstring(session_id2, servicename);
/* pamsshagentauth_debug3("pwd: %s", pwd); */
if(retc)
pamsshagentauth_buffer_put_cstring(session_id2, pwd);
else
pamsshagentauth_buffer_put_cstring(session_id2, "");
/* pamsshagentauth_debug3("action: %s", action_logbuf); */
pamsshagentauth_buffer_put_string(session_id2, action_agentbuf.buf + action_agentbuf.offset, action_agentbuf.end - action_agentbuf.offset);
if (free_logbuf) {
pamsshagentauth_xfree(action_logbuf);
pamsshagentauth_buffer_free(&action_agentbuf);
}
/* pamsshagentauth_debug3("hostname: %s", hostname); */
if(reti >= 0)
pamsshagentauth_buffer_put_cstring(session_id2, hostname);
else
pamsshagentauth_buffer_put_cstring(session_id2, "");
/* pamsshagentauth_debug3("ts: %ld", ts); */
pamsshagentauth_buffer_put_int64(session_id2, (uint64_t) ts);
free(cookie);
return;
}
int
pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename)
{
Buffer session_id2 = { 0 };
Identity *id;
Key *key;
AuthenticationConnection *ac;
char *comment;
uint8_t retval = 0;
uid_t uid = getpwnam(ruser)->pw_uid;
OpenSSL_add_all_digests();
pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename);
if ((ac = ssh_get_authentication_connection(uid))) {
pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2))
{
if(key != NULL) {
id = pamsshagentauth_xcalloc(1, sizeof(*id));
id->key = key;
id->filename = comment;
id->ac = ac;
if(userauth_pubkey_from_id(ruser, id, &session_id2)) {
retval = 1;
}
pamsshagentauth_xfree(id->filename);
pamsshagentauth_key_free(id->key);
pamsshagentauth_xfree(id);
if(retval == 1)
break;
}
}
pamsshagentauth_buffer_free(&session_id2);
ssh_close_authentication_connection(ac);
}
else {
pamsshagentauth_verbose("No ssh-agent could be contacted");
}
/* pamsshagentauth_xfree(session_id2); */
EVP_cleanup();
return retval;
}

36
iterate_ssh_agent_keys.h Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2008, Jamie Beverly.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY Jamie Beverly ``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 Jamie Beverly 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 Jamie Beverly.
*/
#ifndef _ITERATE_SSH_AGENT_KEYS_H
#define _ITERATE_SSH_AGENT_KEYS_H
int pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename);
#endif

159
kex.h Normal file
View File

@ -0,0 +1,159 @@
/* $OpenBSD: kex.h,v 1.46 2007/06/07 19:37:34 pvalchev Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef KEX_H
#define KEX_H
#include <signal.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#define KEX_DH1 "diffie-hellman-group1-sha1"
#define KEX_DH14 "diffie-hellman-group14-sha1"
#define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1"
#define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256"
#define COMP_NONE 0
#define COMP_ZLIB 1
#define COMP_DELAYED 2
enum kex_init_proposals {
PROPOSAL_KEX_ALGS,
PROPOSAL_SERVER_HOST_KEY_ALGS,
PROPOSAL_ENC_ALGS_CTOS,
PROPOSAL_ENC_ALGS_STOC,
PROPOSAL_MAC_ALGS_CTOS,
PROPOSAL_MAC_ALGS_STOC,
PROPOSAL_COMP_ALGS_CTOS,
PROPOSAL_COMP_ALGS_STOC,
PROPOSAL_LANG_CTOS,
PROPOSAL_LANG_STOC,
PROPOSAL_MAX
};
enum kex_modes {
MODE_IN,
MODE_OUT,
MODE_MAX
};
enum kex_exchange {
KEX_DH_GRP1_SHA1,
KEX_DH_GRP14_SHA1,
KEX_DH_GEX_SHA1,
KEX_DH_GEX_SHA256,
KEX_MAX
};
#define KEX_INIT_SENT 0x0001
typedef struct Kex Kex;
typedef struct Mac Mac;
typedef struct Comp Comp;
typedef struct Enc Enc;
typedef struct Newkeys Newkeys;
struct Enc {
char *name;
Cipher *cipher;
int enabled;
u_int key_len;
u_int block_size;
u_char *key;
u_char *iv;
};
struct Mac {
char *name;
int enabled;
u_int mac_len;
u_char *key;
u_int key_len;
int type;
const EVP_MD *evp_md;
HMAC_CTX evp_ctx;
struct umac_ctx *umac_ctx;
};
struct Comp {
int type;
int enabled;
char *name;
};
struct Newkeys {
Enc enc;
Mac mac;
Comp comp;
};
struct Kex {
u_char *session_id;
u_int session_id_len;
Newkeys *newkeys[MODE_MAX];
u_int we_need;
int server;
char *name;
int hostkey_type;
int kex_type;
Buffer my;
Buffer peer;
sig_atomic_t done;
int flags;
const EVP_MD *evp_md;
char *client_version_string;
char *server_version_string;
int (*verify_host_key)(Key *);
Key *(*load_host_key)(int);
int (*host_key_index)(Key *);
void (*kex[KEX_MAX])(Kex *);
};
Kex *kex_setup(char *[PROPOSAL_MAX]);
void kex_finish(Kex *);
void kex_send_kexinit(Kex *);
void kex_input_kexinit(int, u_int32_t, void *);
void kex_derive_keys(Kex *, u_char *, u_int, BIGNUM *);
Newkeys *kex_get_newkeys(int);
void kexdh_client(Kex *);
void kexdh_server(Kex *);
void kexgex_client(Kex *);
void kexgex_server(Kex *);
void
kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *);
void
kexgex_hash(const EVP_MD *, char *, char *, char *, int, char *,
int, u_char *, int, int, int, int, BIGNUM *, BIGNUM *, BIGNUM *,
BIGNUM *, BIGNUM *, u_char **, u_int *);
void
derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]);
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
void dump_digest(char *, u_char *, int);
#endif
#endif

873
key.c Normal file
View File

@ -0,0 +1,873 @@
/* $OpenBSD: key.c,v 1.69 2007/07/12 05:48:05 ray Exp $ */
/*
* read_bignum():
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* Copyright (c) 2000, 2001 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
/*
* My single line "return -1; / * avoid compiler warning * / is licensed
* under same BSD style license as the remainder of this file.
* Feel free to use it for any purpose... ... ... Jamie Beverly ... ... ...
*/
#include "includes.h"
#include <sys/types.h>
#include <openssl/evp.h>
#include <openbsd-compat/openssl-compat.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "xmalloc.h"
#include "key.h"
#include "rsa.h"
#include "uuencode.h"
#include "buffer.h"
#include "log.h"
Key *
pamsshagentauth_key_new(int type)
{
Key *k;
RSA *rsa;
DSA *dsa;
k = pamsshagentauth_xcalloc(1, sizeof(*k));
k->type = type;
k->dsa = NULL;
k->rsa = NULL;
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
if ((rsa = RSA_new()) == NULL)
pamsshagentauth_fatal("key_new: RSA_new failed");
if ((rsa->n = BN_new()) == NULL)
pamsshagentauth_fatal("key_new: BN_new failed");
if ((rsa->e = BN_new()) == NULL)
pamsshagentauth_fatal("key_new: BN_new failed");
k->rsa = rsa;
break;
case KEY_DSA:
if ((dsa = DSA_new()) == NULL)
pamsshagentauth_fatal("key_new: DSA_new failed");
if ((dsa->p = BN_new()) == NULL)
pamsshagentauth_fatal("key_new: BN_new failed");
if ((dsa->q = BN_new()) == NULL)
pamsshagentauth_fatal("key_new: BN_new failed");
if ((dsa->g = BN_new()) == NULL)
pamsshagentauth_fatal("key_new: BN_new failed");
if ((dsa->pub_key = BN_new()) == NULL)
pamsshagentauth_fatal("key_new: BN_new failed");
k->dsa = dsa;
break;
case KEY_UNSPEC:
break;
default:
pamsshagentauth_fatal("key_new: bad key type %d", k->type);
break;
}
return k;
}
Key *
pamsshagentauth_key_new_private(int type)
{
Key *k = pamsshagentauth_key_new(type);
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
if ((k->rsa->d = BN_new()) == NULL)
pamsshagentauth_fatal("key_new_private: BN_new failed");
if ((k->rsa->iqmp = BN_new()) == NULL)
pamsshagentauth_fatal("key_new_private: BN_new failed");
if ((k->rsa->q = BN_new()) == NULL)
pamsshagentauth_fatal("key_new_private: BN_new failed");
if ((k->rsa->p = BN_new()) == NULL)
pamsshagentauth_fatal("key_new_private: BN_new failed");
if ((k->rsa->dmq1 = BN_new()) == NULL)
pamsshagentauth_fatal("key_new_private: BN_new failed");
if ((k->rsa->dmp1 = BN_new()) == NULL)
pamsshagentauth_fatal("key_new_private: BN_new failed");
break;
case KEY_DSA:
if ((k->dsa->priv_key = BN_new()) == NULL)
pamsshagentauth_fatal("key_new_private: BN_new failed");
break;
case KEY_UNSPEC:
break;
default:
break;
}
return k;
}
void
pamsshagentauth_key_free(Key *k)
{
if (k == NULL)
pamsshagentauth_fatal("key_free: key is NULL");
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
if (k->rsa != NULL)
RSA_free(k->rsa);
k->rsa = NULL;
break;
case KEY_DSA:
if (k->dsa != NULL)
DSA_free(k->dsa);
k->dsa = NULL;
break;
case KEY_UNSPEC:
break;
default:
pamsshagentauth_fatal("key_free: bad key type %d", k->type);
break;
}
pamsshagentauth_xfree(k);
}
int
pamsshagentauth_key_equal(const Key *a, const Key *b)
{
if (a == NULL || b == NULL || a->type != b->type)
return 0;
switch (a->type) {
case KEY_RSA1:
case KEY_RSA:
return a->rsa != NULL && b->rsa != NULL &&
BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
BN_cmp(a->rsa->n, b->rsa->n) == 0;
case KEY_DSA:
return a->dsa != NULL && b->dsa != NULL &&
BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
default:
pamsshagentauth_fatal("key_equal: bad key type %d", a->type);
}
return -1; /* avoid compiler warning */
}
u_char*
pamsshagentauth_key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
u_int *dgst_raw_length)
{
const EVP_MD *md = NULL;
EVP_MD_CTX ctx;
u_char *blob = NULL;
u_char *retval = NULL;
u_int len = 0;
int nlen, elen;
*dgst_raw_length = 0;
switch (dgst_type) {
case SSH_FP_MD5:
md = EVP_md5();
break;
case SSH_FP_SHA1:
md = EVP_sha1();
break;
default:
pamsshagentauth_fatal("key_fingerprint_raw: bad digest type %d",
dgst_type);
}
switch (k->type) {
case KEY_RSA1:
nlen = BN_num_bytes(k->rsa->n);
elen = BN_num_bytes(k->rsa->e);
len = nlen + elen;
blob = pamsshagentauth_xmalloc(len);
BN_bn2bin(k->rsa->n, blob);
BN_bn2bin(k->rsa->e, blob + nlen);
break;
case KEY_DSA:
case KEY_RSA:
pamsshagentauth_key_to_blob(k, &blob, &len);
break;
case KEY_UNSPEC:
return retval;
default:
pamsshagentauth_fatal("key_fingerprint_raw: bad key type %d", k->type);
break;
}
if (blob != NULL) {
retval = pamsshagentauth_xmalloc(EVP_MAX_MD_SIZE);
EVP_DigestInit(&ctx, md);
EVP_DigestUpdate(&ctx, blob, len);
EVP_DigestFinal(&ctx, retval, dgst_raw_length);
memset(blob, 0, len);
pamsshagentauth_xfree(blob);
} else {
pamsshagentauth_fatal("key_fingerprint_raw: blob is null");
}
return retval;
}
static char *
key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
{
char *retval;
u_int i;
retval = pamsshagentauth_xcalloc(1, dgst_raw_len * 3 + 1);
for (i = 0; i < dgst_raw_len; i++) {
char hex[4];
snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
pamsshagentauth_strlcat(retval, hex, dgst_raw_len * 3 + 1);
}
/* Remove the trailing ':' character */
retval[(dgst_raw_len * 3) - 1] = '\0';
return retval;
}
static char *
key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
{
char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
u_int i, j = 0, rounds, seed = 1;
char *retval;
rounds = (dgst_raw_len / 2) + 1;
retval = pamsshagentauth_xcalloc((rounds * 6), sizeof(char));
retval[j++] = 'x';
for (i = 0; i < rounds; i++) {
u_int idx0, idx1, idx2, idx3, idx4;
if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
seed) % 6;
idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
(seed / 6)) % 6;
retval[j++] = vowels[idx0];
retval[j++] = consonants[idx1];
retval[j++] = vowels[idx2];
if ((i + 1) < rounds) {
idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
retval[j++] = consonants[idx3];
retval[j++] = '-';
retval[j++] = consonants[idx4];
seed = ((seed * 5) +
((((u_int)(dgst_raw[2 * i])) * 7) +
((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
}
} else {
idx0 = seed % 6;
idx1 = 16;
idx2 = seed / 6;
retval[j++] = vowels[idx0];
retval[j++] = consonants[idx1];
retval[j++] = vowels[idx2];
}
}
retval[j++] = 'x';
retval[j++] = '\0';
return retval;
}
char *
pamsshagentauth_key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
{
char *retval = NULL;
u_char *dgst_raw;
u_int dgst_raw_len;
dgst_raw = pamsshagentauth_key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
if (!dgst_raw)
pamsshagentauth_fatal("key_fingerprint: null from pamsshagentauth_key_fingerprint_raw()");
switch (dgst_rep) {
case SSH_FP_HEX:
retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
break;
case SSH_FP_BUBBLEBABBLE:
retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
break;
default:
pamsshagentauth_fatal("key_fingerprint_ex: bad digest representation %d",
dgst_rep);
break;
}
memset(dgst_raw, 0, dgst_raw_len);
pamsshagentauth_xfree(dgst_raw);
return retval;
}
/*
* Reads a multiple-precision integer in decimal from the buffer, and advances
* the pointer. The integer must already be initialized. This function is
* permitted to modify the buffer. This leaves *cpp to point just beyond the
* last processed (and maybe modified) character. Note that this may modify
* the buffer containing the number.
*/
static int
read_bignum(char **cpp, BIGNUM * value)
{
char *cp = *cpp;
int old;
/* Skip any leading whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
/* Check that it begins with a decimal digit. */
if (*cp < '0' || *cp > '9')
return 0;
/* Save starting position. */
*cpp = cp;
/* Move forward until all decimal digits skipped. */
for (; *cp >= '0' && *cp <= '9'; cp++)
;
/* Save the old terminating character, and replace it by \0. */
old = *cp;
*cp = 0;
/* Parse the number. */
if (BN_dec2bn(&value, *cpp) == 0)
return 0;
/* Restore old terminating character. */
*cp = old;
/* Move beyond the number and return success. */
*cpp = cp;
return 1;
}
static int
write_bignum(FILE *f, BIGNUM *num)
{
char *buf = BN_bn2dec(num);
if (buf == NULL) {
pamsshagentauth_logerror("write_bignum: BN_bn2dec() failed");
return 0;
}
fprintf(f, " %s", buf);
OPENSSL_free(buf);
return 1;
}
/* returns 1 ok, -1 error */
int
pamsshagentauth_key_read(Key *ret, char **cpp)
{
Key *k;
int success = -1;
char *cp, *space;
int len, n, type;
u_int bits;
u_char *blob;
cp = *cpp;
switch (ret->type) {
case KEY_RSA1:
/* Get number of bits. */
if (*cp < '0' || *cp > '9')
return -1; /* Bad bit count... */
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
bits = 10 * bits + *cp - '0';
if (bits == 0)
return -1;
*cpp = cp;
/* Get public exponent, public modulus. */
if (!read_bignum(cpp, ret->rsa->e))
return -1;
if (!read_bignum(cpp, ret->rsa->n))
return -1;
success = 1;
break;
case KEY_UNSPEC:
case KEY_RSA:
case KEY_DSA:
space = strchr(cp, ' ');
if (space == NULL) {
pamsshagentauth_verbose("key_read: missing whitespace");
return -1;
}
*space = '\0';
type = pamsshagentauth_key_type_from_name(cp);
*space = ' ';
if (type == KEY_UNSPEC) {
pamsshagentauth_verbose("key_read: missing keytype");
return -1;
}
cp = space+1;
if (*cp == '\0') {
pamsshagentauth_verbose("key_read: short string");
return -1;
}
if (ret->type == KEY_UNSPEC) {
ret->type = type;
} else if (ret->type != type) {
/* is a key, but different type */
pamsshagentauth_verbose("key_read: type mismatch");
return -1;
}
len = 2*strlen(cp);
blob = pamsshagentauth_xmalloc(len);
n = pamsshagentauth_uudecode(cp, blob, len);
if (n < 0) {
pamsshagentauth_logerror("key_read: uudecode %s failed", cp);
pamsshagentauth_xfree(blob);
return -1;
}
k = pamsshagentauth_key_from_blob(blob, (u_int)n);
pamsshagentauth_xfree(blob);
if (k == NULL) {
pamsshagentauth_logerror("key_read: key_from_blob %s failed", cp);
return -1;
}
if (k->type != type) {
pamsshagentauth_logerror("key_read: type mismatch: encoding error");
pamsshagentauth_key_free(k);
return -1;
}
/*XXXX*/
if (ret->type == KEY_RSA) {
if (ret->rsa != NULL)
RSA_free(ret->rsa);
ret->rsa = k->rsa;
k->rsa = NULL;
success = 1;
#ifdef DEBUG_PK
RSA_print_fp(stderr, ret->rsa, 8);
#endif
} else {
if (ret->dsa != NULL)
DSA_free(ret->dsa);
ret->dsa = k->dsa;
k->dsa = NULL;
success = 1;
#ifdef DEBUG_PK
DSA_print_fp(stderr, ret->dsa, 8);
#endif
}
/*XXXX*/
pamsshagentauth_key_free(k);
if (success != 1)
break;
/* advance cp: skip whitespace and data */
while (*cp == ' ' || *cp == '\t')
cp++;
while (*cp != '\0' && *cp != ' ' && *cp != '\t')
cp++;
*cpp = cp;
break;
default:
pamsshagentauth_fatal("key_read: bad key type: %d", ret->type);
break;
}
return success;
}
int
pamsshagentauth_key_write(const Key *key, FILE *f)
{
int n, success = 0;
u_int len, bits = 0;
u_char *blob;
char *uu;
if (key->type == KEY_RSA1 && key->rsa != NULL) {
/* size of modulus 'n' */
bits = BN_num_bits(key->rsa->n);
fprintf(f, "%u", bits);
if (write_bignum(f, key->rsa->e) &&
write_bignum(f, key->rsa->n)) {
success = 1;
} else {
pamsshagentauth_logerror("key_write: failed for RSA key");
}
} else if ((key->type == KEY_DSA && key->dsa != NULL) ||
(key->type == KEY_RSA && key->rsa != NULL)) {
pamsshagentauth_key_to_blob(key, &blob, &len);
uu = pamsshagentauth_xmalloc(2*len);
n = pamsshagentauth_uuencode(blob, len, uu, 2*len);
if (n > 0) {
fprintf(f, "%s %s", key_ssh_name(key), uu);
success = 1;
}
pamsshagentauth_xfree(blob);
pamsshagentauth_xfree(uu);
}
return success;
}
const char *
pamsshagentauth_key_type(const Key *k)
{
switch (k->type) {
case KEY_RSA1:
return "RSA1";
case KEY_RSA:
return "RSA";
case KEY_DSA:
return "DSA";
}
return "unknown";
}
const char *
key_ssh_name(const Key *k)
{
switch (k->type) {
case KEY_RSA:
return "ssh-rsa";
case KEY_DSA:
return "ssh-dss";
}
return "ssh-unknown";
}
u_int
pamsshagentauth_key_size(const Key *k)
{
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
return BN_num_bits(k->rsa->n);
case KEY_DSA:
return BN_num_bits(k->dsa->p);
}
return 0;
}
static RSA *
rsa_generate_private_key(u_int bits)
{
RSA *private;
private = RSA_generate_key(bits, 35, NULL, NULL);
if (private == NULL)
pamsshagentauth_fatal("rsa_generate_private_key: key generation failed.");
return private;
}
static DSA*
dsa_generate_private_key(u_int bits)
{
DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
if (private == NULL)
pamsshagentauth_fatal("dsa_generate_private_key: DSA_generate_parameters failed");
if (!DSA_generate_key(private))
pamsshagentauth_fatal("dsa_generate_private_key: DSA_generate_key failed.");
if (private == NULL)
pamsshagentauth_fatal("dsa_generate_private_key: NULL.");
return private;
}
Key *
pamsshagentauth_key_generate(int type, u_int bits)
{
Key *k = pamsshagentauth_key_new(KEY_UNSPEC);
switch (type) {
case KEY_DSA:
k->dsa = dsa_generate_private_key(bits);
break;
case KEY_RSA:
case KEY_RSA1:
k->rsa = rsa_generate_private_key(bits);
break;
default:
pamsshagentauth_fatal("key_generate: unknown type %d", type);
}
k->type = type;
return k;
}
Key *
pamsshagentauth_key_from_private(const Key *k)
{
Key *n = NULL;
switch (k->type) {
case KEY_DSA:
n = pamsshagentauth_key_new(k->type);
if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
(BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
(BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
(BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL))
pamsshagentauth_fatal("key_from_private: BN_copy failed");
break;
case KEY_RSA:
case KEY_RSA1:
n = pamsshagentauth_key_new(k->type);
if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
(BN_copy(n->rsa->e, k->rsa->e) == NULL))
pamsshagentauth_fatal("key_from_private: BN_copy failed");
break;
default:
pamsshagentauth_fatal("key_from_private: unknown type %d", k->type);
break;
}
return n;
}
int
pamsshagentauth_key_type_from_name(char *name)
{
if (strcmp(name, "rsa1") == 0) {
return KEY_RSA1;
} else if (strcmp(name, "rsa") == 0) {
return KEY_RSA;
} else if (strcmp(name, "dsa") == 0) {
return KEY_DSA;
} else if (strcmp(name, "ssh-rsa") == 0) {
return KEY_RSA;
} else if (strcmp(name, "ssh-dss") == 0) {
return KEY_DSA;
}
pamsshagentauth_verbose("key_type_from_name: unknown key type '%s'", name);
return KEY_UNSPEC;
}
int
pamsshagentauth_key_names_valid2(const char *names)
{
char *s, *cp, *p;
if (names == NULL || strcmp(names, "") == 0)
return 0;
s = cp = pamsshagentauth_xstrdup(names);
for ((p = strsep(&cp, ",")); p && *p != '\0';
(p = strsep(&cp, ","))) {
switch (pamsshagentauth_key_type_from_name(p)) {
case KEY_RSA1:
case KEY_UNSPEC:
pamsshagentauth_xfree(s);
return 0;
}
}
pamsshagentauth_verbose("key names ok: [%s]", names);
pamsshagentauth_xfree(s);
return 1;
}
Key *
pamsshagentauth_key_from_blob(const u_char *blob, u_int blen)
{
Buffer b;
int rlen, type;
char *ktype = NULL;
Key *key = NULL;
#ifdef DEBUG_PK
pamsshagentauth_dump_base64(stderr, blob, blen);
#endif
pamsshagentauth_buffer_init(&b);
pamsshagentauth_buffer_append(&b, blob, blen);
if ((ktype = pamsshagentauth_buffer_get_string_ret(&b, NULL)) == NULL) {
pamsshagentauth_logerror("key_from_blob: can't read key type");
goto out;
}
type = pamsshagentauth_key_type_from_name(ktype);
switch (type) {
case KEY_RSA:
key = pamsshagentauth_key_new(type);
if (pamsshagentauth_buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
pamsshagentauth_buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
pamsshagentauth_logerror("key_from_blob: can't read rsa key");
pamsshagentauth_key_free(key);
key = NULL;
goto out;
}
#ifdef DEBUG_PK
RSA_print_fp(stderr, key->rsa, 8);
#endif
break;
case KEY_DSA:
key = pamsshagentauth_key_new(type);
if (pamsshagentauth_buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
pamsshagentauth_buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
pamsshagentauth_buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
pamsshagentauth_buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
pamsshagentauth_logerror("key_from_blob: can't read dsa key");
pamsshagentauth_key_free(key);
key = NULL;
goto out;
}
#ifdef DEBUG_PK
DSA_print_fp(stderr, key->dsa, 8);
#endif
break;
case KEY_UNSPEC:
key = pamsshagentauth_key_new(type);
break;
default:
pamsshagentauth_logerror("key_from_blob: cannot handle type %s", ktype);
goto out;
}
rlen = pamsshagentauth_buffer_len(&b);
if (key != NULL && rlen != 0)
pamsshagentauth_logerror("key_from_blob: remaining bytes in key blob %d", rlen);
out:
if (ktype != NULL)
pamsshagentauth_xfree(ktype);
pamsshagentauth_buffer_free(&b);
return key;
}
int
pamsshagentauth_key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
{
Buffer b;
int len;
if (key == NULL) {
pamsshagentauth_logerror("key_to_blob: key == NULL");
return 0;
}
pamsshagentauth_buffer_init(&b);
switch (key->type) {
case KEY_DSA:
pamsshagentauth_buffer_put_cstring(&b, key_ssh_name(key));
pamsshagentauth_buffer_put_bignum2(&b, key->dsa->p);
pamsshagentauth_buffer_put_bignum2(&b, key->dsa->q);
pamsshagentauth_buffer_put_bignum2(&b, key->dsa->g);
pamsshagentauth_buffer_put_bignum2(&b, key->dsa->pub_key);
break;
case KEY_RSA:
pamsshagentauth_buffer_put_cstring(&b, key_ssh_name(key));
pamsshagentauth_buffer_put_bignum2(&b, key->rsa->e);
pamsshagentauth_buffer_put_bignum2(&b, key->rsa->n);
break;
default:
pamsshagentauth_logerror("key_to_blob: unsupported key type %d", key->type);
pamsshagentauth_buffer_free(&b);
return 0;
}
len = pamsshagentauth_buffer_len(&b);
if (lenp != NULL)
*lenp = len;
if (blobp != NULL) {
*blobp = pamsshagentauth_xmalloc(len);
memcpy(*blobp, pamsshagentauth_buffer_ptr(&b), len);
}
memset(pamsshagentauth_buffer_ptr(&b), 0, len);
pamsshagentauth_buffer_free(&b);
return len;
}
int
pamsshagentauth_key_sign(
const Key *key,
u_char **sigp, u_int *lenp,
const u_char *data, u_int datalen)
{
switch (key->type) {
case KEY_DSA:
return ssh_dss_sign(key, sigp, lenp, data, datalen);
case KEY_RSA:
return ssh_rsa_sign(key, sigp, lenp, data, datalen);
default:
pamsshagentauth_logerror("key_sign: invalid key type %d", key->type);
return -1;
}
}
/*
* key_verify returns 1 for a correct signature, 0 for an incorrect signature
* and -1 on error.
*/
int
pamsshagentauth_key_verify(
const Key *key,
const u_char *signature, u_int signaturelen,
const u_char *data, u_int datalen)
{
if (signaturelen == 0)
return -1;
switch (key->type) {
case KEY_DSA:
return ssh_dss_verify(key, signature, signaturelen, data, datalen);
case KEY_RSA:
return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
default:
pamsshagentauth_logerror("key_verify: invalid key type %d", key->type);
return -1;
}
}
/* Converts a private to a public key */
Key *
pamsshagentauth_key_demote(const Key *k)
{
Key *pk;
pk = pamsshagentauth_xcalloc(1, sizeof(*pk));
pk->type = k->type;
pk->flags = k->flags;
pk->dsa = NULL;
pk->rsa = NULL;
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
if ((pk->rsa = RSA_new()) == NULL)
pamsshagentauth_fatal("key_demote: RSA_new failed");
if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
pamsshagentauth_fatal("key_demote: BN_dup failed");
if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
pamsshagentauth_fatal("key_demote: BN_dup failed");
break;
case KEY_DSA:
if ((pk->dsa = DSA_new()) == NULL)
pamsshagentauth_fatal("key_demote: DSA_new failed");
if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
pamsshagentauth_fatal("key_demote: BN_dup failed");
if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
pamsshagentauth_fatal("key_demote: BN_dup failed");
if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
pamsshagentauth_fatal("key_demote: BN_dup failed");
if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
pamsshagentauth_fatal("key_demote: BN_dup failed");
break;
default:
pamsshagentauth_fatal("key_free: bad key type %d", k->type);
break;
}
return (pk);
}

87
key.h Normal file
View File

@ -0,0 +1,87 @@
/* $OpenBSD: key.h,v 1.26 2006/08/03 03:34:42 deraadt Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef KEY_H
#define KEY_H
#include <openssl/rsa.h>
#include <openssl/dsa.h>
typedef struct Key Key;
enum types {
KEY_RSA1,
KEY_RSA,
KEY_DSA,
KEY_UNSPEC
};
enum fp_type {
SSH_FP_SHA1,
SSH_FP_MD5
};
enum fp_rep {
SSH_FP_HEX,
SSH_FP_BUBBLEBABBLE
};
/* key is stored in external hardware */
#define KEY_FLAG_EXT 0x0001
struct Key {
int type;
int flags;
RSA *rsa;
DSA *dsa;
};
Key *pamsshagentauth_key_new(int);
Key *pamsshagentauth_key_new_private(int);
void pamsshagentauth_key_free(Key *);
Key *pamsshagentauth_key_demote(const Key *);
int pamsshagentauth_key_equal(const Key *, const Key *);
char *pamsshagentauth_key_fingerprint(const Key *, enum fp_type, enum fp_rep);
u_char *pamsshagentauth_key_fingerprint_raw(const Key *, enum fp_type, u_int *);
const char *pamsshagentauth_key_type(const Key *);
int pamsshagentauth_key_write(const Key *, FILE *);
int pamsshagentauth_key_read(Key *, char **);
u_int pamsshagentauth_key_size(const Key *);
Key *pamsshagentauth_key_generate(int, u_int);
Key *pamsshagentauth_key_from_private(const Key *);
int pamsshagentauth_key_type_from_name(char *);
Key *pamsshagentauth_key_from_blob(const u_char *, u_int);
int pamsshagentauth_key_to_blob(const Key *, u_char **, u_int *);
const char *key_ssh_name(const Key *);
int pamsshagentauth_key_names_valid2(const char *);
int pamsshagentauth_key_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
int pamsshagentauth_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
int ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
#endif

394
log.c Normal file
View File

@ -0,0 +1,394 @@
/* $OpenBSD: log.c,v 1.40 2007/05/17 07:50:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/*
* Copyright (c) 2000 Markus Friedl. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "includes.h"
#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <errno.h>
#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H)
# include <vis.h>
#endif
#include "xmalloc.h"
#include "log.h"
static LogLevel log_level = SYSLOG_LEVEL_INFO;
static int log_on_stderr = 1;
static int log_facility = LOG_AUTH;
static char *argv0;
extern char *__progname;
#define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL)
#define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL)
#define UNUSED(expr) do { (void)(expr); } while (0)
/* textual representation of log-facilities/levels */
static struct {
const char *name;
SyslogFacility val;
} log_facilities[] = {
{ "DAEMON", SYSLOG_FACILITY_DAEMON },
{ "USER", SYSLOG_FACILITY_USER },
{ "AUTH", SYSLOG_FACILITY_AUTH },
#ifdef LOG_AUTHPRIV
{ "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV },
#endif
{ "LOCAL0", SYSLOG_FACILITY_LOCAL0 },
{ "LOCAL1", SYSLOG_FACILITY_LOCAL1 },
{ "LOCAL2", SYSLOG_FACILITY_LOCAL2 },
{ "LOCAL3", SYSLOG_FACILITY_LOCAL3 },
{ "LOCAL4", SYSLOG_FACILITY_LOCAL4 },
{ "LOCAL5", SYSLOG_FACILITY_LOCAL5 },
{ "LOCAL6", SYSLOG_FACILITY_LOCAL6 },
{ "LOCAL7", SYSLOG_FACILITY_LOCAL7 },
{ NULL, SYSLOG_FACILITY_NOT_SET }
};
static struct {
const char *name;
LogLevel val;
} log_levels[] =
{
{ "QUIET", SYSLOG_LEVEL_QUIET },
{ "FATAL", SYSLOG_LEVEL_FATAL },
{ "ERROR", SYSLOG_LEVEL_ERROR },
{ "INFO", SYSLOG_LEVEL_INFO },
{ "VERBOSE", SYSLOG_LEVEL_VERBOSE },
{ "DEBUG", SYSLOG_LEVEL_DEBUG1 },
{ "DEBUG1", SYSLOG_LEVEL_DEBUG1 },
{ "DEBUG2", SYSLOG_LEVEL_DEBUG2 },
{ "DEBUG3", SYSLOG_LEVEL_DEBUG3 },
{ NULL, SYSLOG_LEVEL_NOT_SET }
};
SyslogFacility
pamsshagentauth_log_facility_number(char *name)
{
int i;
if (name != NULL)
for (i = 0; log_facilities[i].name; i++)
if (strcasecmp(log_facilities[i].name, name) == 0)
return log_facilities[i].val;
return SYSLOG_FACILITY_NOT_SET;
}
LogLevel
pamsshagentauth_log_level_number(char *name)
{
int i;
if (name != NULL)
for (i = 0; log_levels[i].name; i++)
if (strcasecmp(log_levels[i].name, name) == 0)
return log_levels[i].val;
return SYSLOG_LEVEL_NOT_SET;
}
/* Error messages that should be logged. */
void
pamsshagentauth_logerror(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
pamsshagentauth_do_log(SYSLOG_LEVEL_ERROR, fmt, args);
va_end(args);
}
void
pamsshagentauth_sigdie(const char *fmt,...)
{
#ifdef DO_LOG_SAFE_IN_SIGHAND
va_list args;
va_start(args, fmt);
pamsshagentauth_do_log(SYSLOG_LEVEL_FATAL, fmt, args);
va_end(args);
#else
UNUSED(fmt);
#endif
_exit(1);
}
/* Log this message (information that usually should go to the log). */
void
pamsshagentauth_logit(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
pamsshagentauth_do_log(SYSLOG_LEVEL_INFO, fmt, args);
va_end(args);
}
/* More detailed messages (information that does not need to go to the log). */
void
pamsshagentauth_verbose(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
pamsshagentauth_do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
va_end(args);
}
/* Debugging messages that should not be logged during normal operation. */
void
pamsshagentauth_debug(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
pamsshagentauth_do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
va_end(args);
}
void
pamsshagentauth_debug2(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
pamsshagentauth_do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
va_end(args);
}
void
pamsshagentauth_debug3(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
pamsshagentauth_do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
va_end(args);
}
/*
* Initialize the log.
*/
void
pamsshagentauth_log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
{
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
struct syslog_data sdata = SYSLOG_DATA_INIT;
#endif
argv0 = av0;
switch (level) {
case SYSLOG_LEVEL_QUIET:
case SYSLOG_LEVEL_FATAL:
case SYSLOG_LEVEL_ERROR:
case SYSLOG_LEVEL_INFO:
case SYSLOG_LEVEL_VERBOSE:
case SYSLOG_LEVEL_DEBUG1:
case SYSLOG_LEVEL_DEBUG2:
case SYSLOG_LEVEL_DEBUG3:
log_level = level;
break;
default:
fprintf(stderr, "Unrecognized internal syslog level code %d\n",
(int) level);
exit(1);
}
log_on_stderr = on_stderr;
if (on_stderr)
return;
switch (facility) {
case SYSLOG_FACILITY_DAEMON:
log_facility = LOG_DAEMON;
break;
case SYSLOG_FACILITY_USER:
log_facility = LOG_USER;
break;
case SYSLOG_FACILITY_AUTH:
log_facility = LOG_AUTH;
break;
#ifdef LOG_AUTHPRIV
case SYSLOG_FACILITY_AUTHPRIV:
log_facility = LOG_AUTHPRIV;
break;
#endif
case SYSLOG_FACILITY_LOCAL0:
log_facility = LOG_LOCAL0;
break;
case SYSLOG_FACILITY_LOCAL1:
log_facility = LOG_LOCAL1;
break;
case SYSLOG_FACILITY_LOCAL2:
log_facility = LOG_LOCAL2;
break;
case SYSLOG_FACILITY_LOCAL3:
log_facility = LOG_LOCAL3;
break;
case SYSLOG_FACILITY_LOCAL4:
log_facility = LOG_LOCAL4;
break;
case SYSLOG_FACILITY_LOCAL5:
log_facility = LOG_LOCAL5;
break;
case SYSLOG_FACILITY_LOCAL6:
log_facility = LOG_LOCAL6;
break;
case SYSLOG_FACILITY_LOCAL7:
log_facility = LOG_LOCAL7;
break;
default:
fprintf(stderr,
"Unrecognized internal syslog facility code %d\n",
(int) facility);
exit(1);
}
/*
* If an external library (eg libwrap) attempts to use syslog
* immediately after reexec, syslog may be pointing to the wrong
* facility, so we force an open/close of syslog here.
*/
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
closelog_r(&sdata);
#else
openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
closelog();
#endif
}
#define MSGBUFSIZ 1024
void
pamsshagentauth_do_log(LogLevel level, const char *fmt, va_list args)
{
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
struct syslog_data sdata = SYSLOG_DATA_INIT;
#endif
char msgbuf[MSGBUFSIZ];
char fmtbuf[MSGBUFSIZ];
char *txt = NULL;
char *preface = "pam_ssh_agent_auth";
int pri = LOG_INFO;
int saved_errno = errno;
if (level > log_level)
return;
switch (level) {
case SYSLOG_LEVEL_FATAL:
if (!log_on_stderr)
txt = "fatal";
pri = LOG_CRIT;
break;
case SYSLOG_LEVEL_ERROR:
if (!log_on_stderr)
txt = "error";
pri = LOG_ERR;
break;
case SYSLOG_LEVEL_INFO:
pri = LOG_INFO;
break;
case SYSLOG_LEVEL_VERBOSE:
pri = LOG_INFO;
break;
case SYSLOG_LEVEL_DEBUG1:
txt = "debug1";
pri = LOG_DEBUG;
break;
case SYSLOG_LEVEL_DEBUG2:
txt = "debug2";
pri = LOG_DEBUG;
break;
case SYSLOG_LEVEL_DEBUG3:
txt = "debug3";
pri = LOG_DEBUG;
break;
default:
txt = "internal error";
pri = LOG_ERR;
break;
}
if (txt != NULL) {
snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s: %s", preface, txt, fmt);
vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
} else {
snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", preface, fmt);
vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
}
pamsshagentauth_strnvis(fmtbuf, msgbuf, sizeof(fmtbuf),
log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS);
if(level == SYSLOG_LEVEL_FATAL) {
snprintf(msgbuf, sizeof msgbuf, "%s\r\nThis incident has been reported to the authorities\r\n", fmtbuf);
if (write(STDERR_FILENO, msgbuf, strlen(msgbuf)) < 0) {
_exit(0);
}
}
if (log_on_stderr) {
snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf);
if (write(STDERR_FILENO, msgbuf, strlen(msgbuf)) < 0) {
_exit(0);
}
} else {
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
syslog_r(pri, &sdata, "%.500s", fmtbuf);
closelog_r(&sdata);
#else
openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
syslog(pri, "%.500s", fmtbuf);
closelog();
#endif
}
errno = saved_errno;
}

66
log.h Normal file
View File

@ -0,0 +1,66 @@
/* $OpenBSD: log.h,v 1.15 2006/08/18 09:13:25 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#ifndef SSH_LOG_H
#define SSH_LOG_H
#include <stdarg.h>
/* Supported syslog facilities and levels. */
typedef enum {
SYSLOG_FACILITY_DAEMON,
SYSLOG_FACILITY_USER,
SYSLOG_FACILITY_AUTH,
#ifdef LOG_AUTHPRIV
SYSLOG_FACILITY_AUTHPRIV,
#endif
SYSLOG_FACILITY_LOCAL0,
SYSLOG_FACILITY_LOCAL1,
SYSLOG_FACILITY_LOCAL2,
SYSLOG_FACILITY_LOCAL3,
SYSLOG_FACILITY_LOCAL4,
SYSLOG_FACILITY_LOCAL5,
SYSLOG_FACILITY_LOCAL6,
SYSLOG_FACILITY_LOCAL7,
SYSLOG_FACILITY_NOT_SET = -1
} SyslogFacility;
typedef enum {
SYSLOG_LEVEL_QUIET,
SYSLOG_LEVEL_FATAL,
SYSLOG_LEVEL_ERROR,
SYSLOG_LEVEL_INFO,
SYSLOG_LEVEL_VERBOSE,
SYSLOG_LEVEL_DEBUG1,
SYSLOG_LEVEL_DEBUG2,
SYSLOG_LEVEL_DEBUG3,
SYSLOG_LEVEL_NOT_SET = -1
} LogLevel;
void pamsshagentauth_log_init(char *, LogLevel, SyslogFacility, int);
SyslogFacility pamsshagentauth_log_facility_number(char *);
LogLevel pamsshagentauth_log_level_number(char *);
void pamsshagentauth_fatal(const char *, ...) __dead __attribute__((format(printf, 1, 2)));
void pamsshagentauth_logerror(const char *, ...) __attribute__((format(printf, 1, 2)));
void pamsshagentauth_sigdie(const char *, ...) __attribute__((format(printf, 1, 2)));
void pamsshagentauth_logit(const char *, ...) __attribute__((format(printf, 1, 2)));
void pamsshagentauth_verbose(const char *, ...) __attribute__((format(printf, 1, 2)));
void pamsshagentauth_debug(const char *, ...) __attribute__((format(printf, 1, 2)));
void pamsshagentauth_debug2(const char *, ...) __attribute__((format(printf, 1, 2)));
void pamsshagentauth_debug3(const char *, ...) __attribute__((format(printf, 1, 2)));
void pamsshagentauth_do_log(LogLevel, const char *, va_list);
void pamsshagentauth_cleanup_exit(int) __dead;
#endif

24
match.h Normal file
View File

@ -0,0 +1,24 @@
/* $OpenBSD: match.h,v 1.13 2006/03/25 22:22:43 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#ifndef MATCH_H
#define MATCH_H
int match_pattern(const char *, const char *);
int match_pattern_list(const char *, const char *, u_int, int);
int match_hostname(const char *, const char *, u_int);
int match_host_and_ip(const char *, const char *, const char *);
int match_user(const char *, const char *, const char *, const char *);
char *match_list(const char *, const char *, u_int *);
#endif

838
misc.c Normal file
View File

@ -0,0 +1,838 @@
/* $OpenBSD: misc.c,v 1.67 2008/01/01 08:47:04 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005,2006 Damien Miller. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "includes.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#include <pwd.h>
#endif
#ifdef SSH_TUN_OPENBSD
#include <net/if.h>
#endif
#include "xmalloc.h"
#include "misc.h"
#include "log.h"
#include "ssh.h"
#define UNUSED(expr) do { (void)(expr); } while (0)
/* remove newline at end of string */
char *
pamsshagentauth_chop(char *s)
{
char *t = s;
while (*t) {
if (*t == '\n' || *t == '\r') {
*t = '\0';
return s;
}
t++;
}
return s;
}
/* set/unset filedescriptor to non-blocking */
int
pamsshagentauth_set_nonblock(int fd)
{
int val;
val = fcntl(fd, F_GETFL, 0);
if (val < 0) {
pamsshagentauth_logerror("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
return (-1);
}
if (val & O_NONBLOCK) {
pamsshagentauth_verbose("fd %d is O_NONBLOCK", fd);
return (0);
}
pamsshagentauth_verbose("fd %d setting O_NONBLOCK", fd);
val |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, val) == -1) {
pamsshagentauth_verbose("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd,
strerror(errno));
return (-1);
}
return (0);
}
int
pamsshagentauth_unset_nonblock(int fd)
{
int val;
val = fcntl(fd, F_GETFL, 0);
if (val < 0) {
pamsshagentauth_logerror("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
return (-1);
}
if (!(val & O_NONBLOCK)) {
pamsshagentauth_verbose("fd %d is not O_NONBLOCK", fd);
return (0);
}
pamsshagentauth_verbose("fd %d clearing O_NONBLOCK", fd);
val &= ~O_NONBLOCK;
if (fcntl(fd, F_SETFL, val) == -1) {
pamsshagentauth_verbose("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s",
fd, strerror(errno));
return (-1);
}
return (0);
}
const char *
ssh_gai_strerror(int gaierr)
{
if (gaierr == EAI_SYSTEM)
return strerror(errno);
return gai_strerror(gaierr);
}
/* disable nagle on socket */
void
pamsshagentauth_set_nodelay(int fd)
{
int opt;
socklen_t optlen;
optlen = sizeof opt;
if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
pamsshagentauth_verbose("getsockopt TCP_NODELAY: %.100s", strerror(errno));
return;
}
if (opt == 1) {
pamsshagentauth_verbose("fd %d is TCP_NODELAY", fd);
return;
}
opt = 1;
pamsshagentauth_verbose("fd %d setting TCP_NODELAY", fd);
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
pamsshagentauth_logerror("setsockopt TCP_NODELAY: %.100s", strerror(errno));
}
/* Characters considered whitespace in strsep calls. */
#define WHITESPACE " \t\r\n"
#define QUOTE "\""
/* return next token in configuration line */
char *
pamsshagentauth_strdelim(char **s)
{
char *old;
int wspace = 0;
if (*s == NULL)
return NULL;
old = *s;
*s = strpbrk(*s, WHITESPACE QUOTE "=");
if (*s == NULL)
return (old);
if (*s[0] == '\"') {
memmove(*s, *s + 1, strlen(*s)); /* move nul too */
/* Find matching quote */
if ((*s = strpbrk(*s, QUOTE)) == NULL) {
return (NULL); /* no matching quote */
} else {
*s[0] = '\0';
return (old);
}
}
/* Allow only one '=' to be skipped */
if (*s[0] == '=')
wspace = 1;
*s[0] = '\0';
/* Skip any extra whitespace after first token */
*s += strspn(*s + 1, WHITESPACE) + 1;
if (*s[0] == '=' && !wspace)
*s += strspn(*s + 1, WHITESPACE) + 1;
return (old);
}
struct passwd *
pamsshagentauth_pwcopy(struct passwd *pw)
{
struct passwd *copy = pamsshagentauth_xcalloc(1, sizeof(*copy));
copy->pw_name = pamsshagentauth_xstrdup(pw->pw_name);
copy->pw_passwd = pamsshagentauth_xstrdup(pw->pw_passwd);
copy->pw_gecos = pamsshagentauth_xstrdup(pw->pw_gecos);
copy->pw_uid = pw->pw_uid;
copy->pw_gid = pw->pw_gid;
#ifdef HAVE_PW_EXPIRE_IN_PASSWD
copy->pw_expire = pw->pw_expire;
#endif
#ifdef HAVE_PW_CHANGE_IN_PASSWD
copy->pw_change = pw->pw_change;
#endif
#ifdef HAVE_PW_CLASS_IN_PASSWD
copy->pw_class = pamsshagentauth_xstrdup(pw->pw_class);
#endif
copy->pw_dir = pamsshagentauth_xstrdup(pw->pw_dir);
copy->pw_shell = pamsshagentauth_xstrdup(pw->pw_shell);
return copy;
}
/*
* Convert ASCII string to TCP/IP port number.
* Port must be >0 and <=65535.
* Return 0 if invalid.
*/
int
pamsshagentauth_a2port(const char *s)
{
long port;
char *endp;
errno = 0;
port = strtol(s, &endp, 0);
if (s == endp || *endp != '\0' ||
(errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) ||
port <= 0 || port > 65535)
return 0;
return port;
}
int
pamsshagentauth_a2tun(const char *s, int *remote)
{
const char *errstr = NULL;
char *sp, *ep;
int tun;
if (remote != NULL) {
*remote = SSH_TUNID_ANY;
sp = pamsshagentauth_xstrdup(s);
if ((ep = strchr(sp, ':')) == NULL) {
pamsshagentauth_xfree(sp);
return (pamsshagentauth_a2tun(s, NULL));
}
ep[0] = '\0'; ep++;
*remote = pamsshagentauth_a2tun(ep, NULL);
tun = pamsshagentauth_a2tun(sp, NULL);
pamsshagentauth_xfree(sp);
return (*remote == SSH_TUNID_ERR ? *remote : tun);
}
if (strcasecmp(s, "any") == 0)
return (SSH_TUNID_ANY);
tun = pamsshagentauth_strtonum(s, 0, SSH_TUNID_MAX, &errstr);
if (errstr != NULL)
return (SSH_TUNID_ERR);
return (tun);
}
#define SECONDS 1
#define MINUTES (SECONDS * 60)
#define HOURS (MINUTES * 60)
#define DAYS (HOURS * 24)
#define WEEKS (DAYS * 7)
/*
* Convert a time string into seconds; format is
* a sequence of:
* time[qualifier]
*
* Valid time qualifiers are:
* <none> seconds
* s|S seconds
* m|M minutes
* h|H hours
* d|D days
* w|W weeks
*
* Examples:
* 90m 90 minutes
* 1h30m 90 minutes
* 2d 2 days
* 1w 1 week
*
* Return -1 if time string is invalid.
*/
long
pamsshagentauth_convtime(const char *s)
{
long total, secs;
const char *p;
char *endp;
errno = 0;
total = 0;
p = s;
if (p == NULL || *p == '\0')
return -1;
while (*p) {
secs = strtol(p, &endp, 10);
if (p == endp ||
(errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
secs < 0)
return -1;
switch (*endp++) {
case '\0':
endp--;
break;
case 's':
case 'S':
break;
case 'm':
case 'M':
secs *= MINUTES;
break;
case 'h':
case 'H':
secs *= HOURS;
break;
case 'd':
case 'D':
secs *= DAYS;
break;
case 'w':
case 'W':
secs *= WEEKS;
break;
default:
return -1;
}
total += secs;
if (total < 0)
return -1;
p = endp;
}
return total;
}
/*
* Returns a standardized host+port identifier string.
* Caller must free returned string.
*/
char *
pamsshagentauth_put_host_port(const char *host, u_short port)
{
char *hoststr;
if (port == 0 || port == SSH_DEFAULT_PORT)
return(pamsshagentauth_xstrdup(host));
if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0)
pamsshagentauth_fatal("put_host_port: asprintf: %s", strerror(errno));
pamsshagentauth_verbose("put_host_port: %s", hoststr);
return hoststr;
}
/*
* Search for next delimiter between hostnames/addresses and ports.
* Argument may be modified (for termination).
* Returns *cp if parsing succeeds.
* *cp is set to the start of the next delimiter, if one was found.
* If this is the last field, *cp is set to NULL.
*/
char *
pamsshagentauth_hpdelim(char **cp)
{
char *s, *old;
if (cp == NULL || *cp == NULL)
return NULL;
old = s = *cp;
if (*s == '[') {
if ((s = strchr(s, ']')) == NULL)
return NULL;
else
s++;
} else if ((s = strpbrk(s, ":/")) == NULL)
s = *cp + strlen(*cp); /* skip to end (see first case below) */
switch (*s) {
case '\0':
*cp = NULL; /* no more fields*/
break;
case ':':
case '/':
*s = '\0'; /* terminate */
*cp = s + 1;
break;
default:
return NULL;
}
return old;
}
char *
pamsshagentauth_cleanhostname(char *host)
{
if (*host == '[' && host[strlen(host) - 1] == ']') {
host[strlen(host) - 1] = '\0';
return (host + 1);
} else
return host;
}
char *
pamsshagentauth_colon(char *cp)
{
int flag = 0;
if (*cp == ':') /* Leading colon is part of file name. */
return (0);
if (*cp == '[')
flag = 1;
for (; *cp; ++cp) {
if (*cp == '@' && *(cp+1) == '[')
flag = 1;
if (*cp == ']' && *(cp+1) == ':' && flag)
return (cp+1);
if (*cp == ':' && !flag)
return (cp);
if (*cp == '/')
return (0);
}
return (0);
}
/* function to assist building execv() arguments */
void
pamsshagentauth_addargs(arglist *args, char *fmt, ...)
{
va_list ap;
char *cp;
u_int nalloc;
int r;
va_start(ap, fmt);
r = vasprintf(&cp, fmt, ap);
va_end(ap);
if (r == -1)
pamsshagentauth_fatal("addargs: argument too long");
nalloc = args->nalloc;
if (args->list == NULL) {
nalloc = 32;
args->num = 0;
} else if (args->num+2 >= nalloc)
nalloc *= 2;
args->list = pamsshagentauth_xrealloc(args->list, nalloc, sizeof(char *));
args->nalloc = nalloc;
args->list[args->num++] = cp;
args->list[args->num] = NULL;
}
void
pamsshagentauth_replacearg(arglist *args, u_int which, char *fmt, ...)
{
va_list ap;
char *cp;
int r;
va_start(ap, fmt);
r = vasprintf(&cp, fmt, ap);
va_end(ap);
if (r == -1)
pamsshagentauth_fatal("replacearg: argument too long");
if (which >= args->num)
pamsshagentauth_fatal("replacearg: tried to replace invalid arg %d >= %d",
which, args->num);
pamsshagentauth_xfree(args->list[which]);
args->list[which] = cp;
}
void
pamsshagentauth_freeargs(arglist *args)
{
u_int i;
if (args->list != NULL) {
for (i = 0; i < args->num; i++)
pamsshagentauth_xfree(args->list[i]);
pamsshagentauth_xfree(args->list);
args->nalloc = args->num = 0;
args->list = NULL;
}
}
/*
* Expands tildes in the file name. Returns data allocated by xmalloc.
* Warning: this calls getpw*.
*/
char *
pamsshagentauth_tilde_expand_filename(const char *filename, uid_t uid)
{
const char *path;
char user[128], ret[MAXPATHLEN];
struct passwd *pw;
u_int len, slash;
if (*filename != '~')
return (pamsshagentauth_xstrdup(filename));
filename++;
path = strchr(filename, '/');
if (path != NULL && path > filename) { /* ~user/path */
slash = path - filename;
if (slash > sizeof(user) - 1)
pamsshagentauth_fatal("tilde_expand_filename: ~username too long");
memcpy(user, filename, slash);
user[slash] = '\0';
if ((pw = getpwnam(user)) == NULL)
pamsshagentauth_fatal("tilde_expand_filename: No such user %s", user);
} else if ((pw = getpwuid(uid)) == NULL) /* ~/path */
pamsshagentauth_fatal("tilde_expand_filename: No such uid %lu", (unsigned long) uid);
if (pamsshagentauth_strlcpy(ret, pw->pw_dir, sizeof(ret)) >= sizeof(ret))
pamsshagentauth_fatal("tilde_expand_filename: Path too long");
/* Make sure directory has a trailing '/' */
len = strlen(pw->pw_dir);
if ((len == 0 || pw->pw_dir[len - 1] != '/') &&
pamsshagentauth_strlcat(ret, "/", sizeof(ret)) >= sizeof(ret))
pamsshagentauth_fatal("tilde_expand_filename: Path too long");
/* Skip leading '/' from specified path */
if (path != NULL)
filename = path + 1;
if (pamsshagentauth_strlcat(ret, filename, sizeof(ret)) >= sizeof(ret))
pamsshagentauth_fatal("tilde_expand_filename: Path too long");
return (pamsshagentauth_xstrdup(ret));
}
/*
* Expand a string with a set of %[char] escapes. A number of escapes may be
* specified as (char *escape_chars, char *replacement) pairs. The list must
* be terminated by a NULL escape_char. Returns replaced string in memory
* allocated by xmalloc.
*/
char *
pamsshagentauth_percent_expand(const char *string, ...)
{
#define EXPAND_MAX_KEYS 16
struct {
const char *key;
const char *repl;
} keys[EXPAND_MAX_KEYS];
u_int num_keys, i, j;
char buf[4096];
va_list ap;
/* Gather keys */
va_start(ap, string);
for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
keys[num_keys].key = va_arg(ap, char *);
if (keys[num_keys].key == NULL)
break;
keys[num_keys].repl = va_arg(ap, char *);
if (keys[num_keys].repl == NULL)
pamsshagentauth_fatal("percent_expand: NULL replacement");
}
va_end(ap);
if (num_keys >= EXPAND_MAX_KEYS)
pamsshagentauth_fatal("percent_expand: too many keys");
/* Expand string */
*buf = '\0';
for (i = 0; *string != '\0'; string++) {
if (*string != '%') {
append:
buf[i++] = *string;
if (i >= sizeof(buf))
pamsshagentauth_fatal("percent_expand: string too long");
buf[i] = '\0';
continue;
}
string++;
if (*string == '%')
goto append;
for (j = 0; j < num_keys; j++) {
if (strchr(keys[j].key, *string) != NULL) {
i = pamsshagentauth_strlcat(buf, keys[j].repl, sizeof(buf));
if (i >= sizeof(buf))
pamsshagentauth_fatal("percent_expand: string too long");
break;
}
}
if (j >= num_keys)
pamsshagentauth_fatal("percent_expand: unknown key %%%c", *string);
}
return (pamsshagentauth_xstrdup(buf));
#undef EXPAND_MAX_KEYS
}
/*
* Read an entire line from a public key file into a static buffer, discarding
* lines that exceed the buffer size. Returns 0 on success, -1 on failure.
*/
int
read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
u_long *lineno)
{
while (fgets(buf, bufsz, f) != NULL) {
if (buf[0] == '\0')
continue;
(*lineno)++;
if (buf[strlen(buf) - 1] == '\n' || feof(f)) {
return 0;
} else {
pamsshagentauth_verbose("%s: %s line %lu exceeds size limit", __func__,
filename, *lineno);
/* discard remainder of line */
while (fgetc(f) != '\n' && !feof(f))
; /* nothing */
}
}
return -1;
}
int
pamsshagentauth_tun_open(int tun, int mode)
{
#if defined(CUSTOM_SYS_TUN_OPEN)
return (sys_tun_open(tun, mode));
#elif defined(SSH_TUN_OPENBSD)
struct ifreq ifr;
char name[100];
int fd = -1, sock;
/* Open the tunnel device */
if (tun <= SSH_TUNID_MAX) {
snprintf(name, sizeof(name), "/dev/tun%d", tun);
fd = open(name, O_RDWR);
} else if (tun == SSH_TUNID_ANY) {
for (tun = 100; tun >= 0; tun--) {
snprintf(name, sizeof(name), "/dev/tun%d", tun);
if ((fd = open(name, O_RDWR)) >= 0)
break;
}
} else {
pamsshagentauth_verbose("%s: invalid tunnel %u", __func__, tun);
return (-1);
}
if (fd < 0) {
pamsshagentauth_verbose("%s: %s open failed: %s", __func__, name, strerror(errno));
return (-1);
}
pamsshagentauth_verbose("%s: %s mode %d fd %d", __func__, name, mode, fd);
/* Set the tunnel device operation mode */
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun);
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
goto failed;
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
goto failed;
/* Set interface mode */
ifr.ifr_flags &= ~IFF_UP;
if (mode == SSH_TUNMODE_ETHERNET)
ifr.ifr_flags |= IFF_LINK0;
else
ifr.ifr_flags &= ~IFF_LINK0;
if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
goto failed;
/* Bring interface up */
ifr.ifr_flags |= IFF_UP;
if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
goto failed;
close(sock);
return (fd);
failed:
if (fd >= 0)
close(fd);
if (sock >= 0)
close(sock);
pamsshagentauth_verbose("%s: failed to set %s mode %d: %s", __func__, name,
mode, strerror(errno));
return (-1);
#else
UNUSED(tun);
UNUSED(mode);
pamsshagentauth_logerror("Tunnel interfaces are not supported on this platform");
return (-1);
#endif
}
void
pamsshagentauth_sanitise_stdfd(void)
{
int nullfd, dupfd;
if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno));
exit(1);
}
while (++dupfd <= 2) {
/* Only clobber closed fds */
if (fcntl(dupfd, F_GETFL, 0) >= 0)
continue;
if (dup2(nullfd, dupfd) == -1) {
fprintf(stderr, "dup2: %s", strerror(errno));
exit(1);
}
}
if (nullfd > 2)
close(nullfd);
}
char *
pamsshagentauth_tohex(const void *vp, size_t l)
{
const u_char *p = (const u_char *)vp;
char b[3], *r;
size_t i, hl;
if (l > 65536)
return pamsshagentauth_xstrdup("tohex: length > 65536");
hl = l * 2 + 1;
r = pamsshagentauth_xcalloc(1, hl);
for (i = 0; i < l; i++) {
snprintf(b, sizeof(b), "%02x", p[i]);
pamsshagentauth_strlcat(r, b, hl);
}
return (r);
}
u_int64_t
pamsshagentauth_get_u64(const void *vp)
{
const u_char *p = (const u_char *)vp;
u_int64_t v;
v = (u_int64_t)p[0] << 56;
v |= (u_int64_t)p[1] << 48;
v |= (u_int64_t)p[2] << 40;
v |= (u_int64_t)p[3] << 32;
v |= (u_int64_t)p[4] << 24;
v |= (u_int64_t)p[5] << 16;
v |= (u_int64_t)p[6] << 8;
v |= (u_int64_t)p[7];
return (v);
}
u_int32_t
pamsshagentauth_get_u32(const void *vp)
{
const u_char *p = (const u_char *)vp;
u_int32_t v;
v = (u_int32_t)p[0] << 24;
v |= (u_int32_t)p[1] << 16;
v |= (u_int32_t)p[2] << 8;
v |= (u_int32_t)p[3];
return (v);
}
u_int16_t
pamsshagentauth_get_u16(const void *vp)
{
const u_char *p = (const u_char *)vp;
u_int16_t v;
v = (u_int16_t)p[0] << 8;
v |= (u_int16_t)p[1];
return (v);
}
void
pamsshagentauth_put_u64(void *vp, u_int64_t v)
{
u_char *p = (u_char *)vp;
p[0] = (u_char)(v >> 56) & 0xff;
p[1] = (u_char)(v >> 48) & 0xff;
p[2] = (u_char)(v >> 40) & 0xff;
p[3] = (u_char)(v >> 32) & 0xff;
p[4] = (u_char)(v >> 24) & 0xff;
p[5] = (u_char)(v >> 16) & 0xff;
p[6] = (u_char)(v >> 8) & 0xff;
p[7] = (u_char)v & 0xff;
}
void
pamsshagentauth_put_u32(void *vp, u_int32_t v)
{
u_char *p = (u_char *)vp;
p[0] = (u_char)(v >> 24) & 0xff;
p[1] = (u_char)(v >> 16) & 0xff;
p[2] = (u_char)(v >> 8) & 0xff;
p[3] = (u_char)v & 0xff;
}
void
pamsshagentauth_put_u16(void *vp, u_int16_t v)
{
u_char *p = (u_char *)vp;
p[0] = (u_char)(v >> 8) & 0xff;
p[1] = (u_char)v & 0xff;
}

91
misc.h Normal file
View File

@ -0,0 +1,91 @@
/* $OpenBSD: misc.h,v 1.37 2007/12/27 14:22:08 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#ifndef _MISC_H
#define _MISC_H
/* misc.c */
char *pamsshagentauth_chop(char *);
char *pamsshagentauth_strdelim(char **);
int pamsshagentauth_set_nonblock(int);
int pamsshagentauth_unset_nonblock(int);
void pamsshagentauth_set_nodelay(int);
int pamsshagentauth_a2port(const char *);
int pamsshagentauth_a2tun(const char *, int *);
char *pamsshagentauth_put_host_port(const char *, u_short);
char *pamsshagentauth_hpdelim(char **);
char *pamsshagentauth_cleanhostname(char *);
char *pamsshagentauth_colon(char *);
long pamsshagentauth_convtime(const char *);
char *pamsshagentauth_tilde_expand_filename(const char *, uid_t);
char *pamsshagentauth_percent_expand(const char *, ...) __attribute__((__sentinel__));
char *pamsshagentauth_tohex(const void *, size_t);
void pamsshagentauth_sanitise_stdfd(void);
struct passwd *pamsshagentauth_pwcopy(struct passwd *);
const char *ssh_gai_strerror(int);
typedef struct arglist arglist;
struct arglist {
char **list;
u_int num;
u_int nalloc;
};
void pamsshagentauth_addargs(arglist *, char *, ...)
__attribute__((format(printf, 2, 3)));
void pamsshagentauth_replacearg(arglist *, u_int, char *, ...)
__attribute__((format(printf, 3, 4)));
void pamsshagentauth_freeargs(arglist *);
int pamsshagentauth_tun_open(int, int);
/* Common definitions for ssh tunnel device forwarding */
#define SSH_TUNMODE_NO 0x00
#define SSH_TUNMODE_POINTOPOINT 0x01
#define SSH_TUNMODE_ETHERNET 0x02
#define SSH_TUNMODE_DEFAULT SSH_TUNMODE_POINTOPOINT
#define SSH_TUNMODE_YES (SSH_TUNMODE_POINTOPOINT|SSH_TUNMODE_ETHERNET)
#define SSH_TUNID_ANY 0x7fffffff
#define SSH_TUNID_ERR (SSH_TUNID_ANY - 1)
#define SSH_TUNID_MAX (SSH_TUNID_ANY - 2)
/* Functions to extract or store big-endian words of various sizes */
u_int64_t pamsshagentauth_get_u64(const void *)
__attribute__((__bounded__( __minbytes__, 1, 8)));
u_int32_t pamsshagentauth_get_u32(const void *)
__attribute__((__bounded__( __minbytes__, 1, 4)));
u_int16_t pamsshagentauth_get_u16(const void *)
__attribute__((__bounded__( __minbytes__, 1, 2)));
void pamsshagentauth_put_u64(void *, u_int64_t)
__attribute__((__bounded__( __minbytes__, 1, 8)));
void pamsshagentauth_put_u32(void *, u_int32_t)
__attribute__((__bounded__( __minbytes__, 1, 4)));
void pamsshagentauth_put_u16(void *, u_int16_t)
__attribute__((__bounded__( __minbytes__, 1, 2)));
/* readpass.c */
#define RP_ECHO 0x0001
#define RP_ALLOW_STDIN 0x0002
#define RP_ALLOW_EOF 0x0004
#define RP_USE_ASKPASS 0x0008
char *read_passphrase(const char *, int);
int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
#endif /* _MISC_H */

40
mkinstalldirs Executable file
View File

@ -0,0 +1,40 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
# $Id: mkinstalldirs,v 1.2 2003/11/21 12:48:55 djm Exp $
errstatus=0
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here

View File

@ -0,0 +1,46 @@
# $Id: Makefile.in,v 1.41 2007/06/25 12:15:13 dtucker Exp $
sysconfdir=@sysconfdir@
piddir=@piddir@
srcdir=@srcdir@
top_srcdir=@top_srcdir@
VPATH=@srcdir@
CC=@CC@
LD=@LD@
CFLAGS=@CFLAGS@
CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@
LIBS=@LIBS@
AR=@AR@
RANLIB=@RANLIB@
INSTALL=@INSTALL@
LDFLAGS=-L. @LDFLAGS@
COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-waitpid.o openssl-compat.o xcrypt.o xmmap.o
OPENBSD=base64.o basename.o daemon.o dirname.o fake-rfc2553.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o port-aix.o port-irix.o port-linux.o port-solaris.o port-uw.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o strtoll.o strtonum.o strtoul.o vis.o
#OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o strtonum.o strtoll.o strtoul.o vis.o
#COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o
PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-uw.o
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
all: libopenbsd-compat.a
$(COMPAT): ../config.h
$(OPENBSD): ../config.h
$(PORTS): ../config.h
libopenbsd-compat.a: $(COMPAT) $(OPENBSD) $(PORTS)
$(AR) rv $@ $(COMPAT) $(OPENBSD) $(PORTS)
$(RANLIB) $@
clean:
rm -f *.o *.a core
distclean: clean
rm -f Makefile *~

315
openbsd-compat/base64.c Normal file
View File

@ -0,0 +1,315 @@
/* $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ */
/*
* Copyright (c) 1996 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/*
* Portions Copyright (c) 1995 by International Business Machines, Inc.
*
* International Business Machines, Inc. (hereinafter called IBM) grants
* permission under its copyrights to use, copy, modify, and distribute this
* Software with or without fee, provided that the above copyright notice and
* all paragraphs of this notice appear in all copies, and that the name of IBM
* not be used in connection with the marketing of any product incorporating
* the Software or modifications thereof, without specific, written prior
* permission.
*
* To the extent it has a right to do so, IBM grants an immunity from suit
* under its patents, if any, for the use, sale or manufacture of products to
* the extent that such products are used for performing Domain Name System
* dynamic updates in TCP/IP networks by means of the Software. No immunity is
* granted for any product per se or for any other function of any product.
*
* THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
* DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
/* OPENBSD ORIGINAL: lib/libc/net/base64.c */
#include "includes.h"
#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON))
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "base64.h"
static const char Base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char Pad64 = '=';
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
The following encoding technique is taken from RFC 1521 by Borenstein
and Freed. It is reproduced here in a slightly edited form for
convenience.
A 65-character subset of US-ASCII is used, enabling 6 bits to be
represented per printable character. (The extra 65th character, "=",
is used to signify a special processing function.)
The encoding process represents 24-bit groups of input bits as output
strings of 4 encoded characters. Proceeding from left to right, a
24-bit input group is formed by concatenating 3 8-bit input groups.
These 24 bits are then treated as 4 concatenated 6-bit groups, each
of which is translated into a single digit in the base64 alphabet.
Each 6-bit group is used as an index into an array of 64 printable
characters. The character referenced by the index is placed in the
output string.
Table 1: The Base64 Alphabet
Value Encoding Value Encoding Value Encoding Value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y
Special processing is performed if fewer than 24 bits are available
at the end of the data being encoded. A full encoding quantum is
always completed at the end of a quantity. When fewer than 24 input
bits are available in an input group, zero bits are added (on the
right) to form an integral number of 6-bit groups. Padding at the
end of the data is performed using the '=' character.
Since all base64 input is an integral number of octets, only the
-------------------------------------------------
following cases can arise:
(1) the final quantum of encoding input is an integral
multiple of 24 bits; here, the final unit of encoded
output will be an integral multiple of 4 characters
with no "=" padding,
(2) the final quantum of encoding input is exactly 8 bits;
here, the final unit of encoded output will be two
characters followed by two "=" padding characters, or
(3) the final quantum of encoding input is exactly 16 bits;
here, the final unit of encoded output will be three
characters followed by one "=" padding character.
*/
#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)
int
pamsshagentauth___b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize)
{
size_t datalength = 0;
u_char input[3];
u_char output[4];
u_int i;
while (2 < srclength) {
input[0] = *src++;
input[1] = *src++;
input[2] = *src++;
srclength -= 3;
output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
output[3] = input[2] & 0x3f;
if (datalength + 4 > targsize)
return (-1);
target[datalength++] = Base64[output[0]];
target[datalength++] = Base64[output[1]];
target[datalength++] = Base64[output[2]];
target[datalength++] = Base64[output[3]];
}
/* Now we worry about padding. */
if (0 != srclength) {
/* Get what's left. */
input[0] = input[1] = input[2] = '\0';
for (i = 0; i < srclength; i++)
input[i] = *src++;
output[0] = input[0] >> 2;
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
if (datalength + 4 > targsize)
return (-1);
target[datalength++] = Base64[output[0]];
target[datalength++] = Base64[output[1]];
if (srclength == 1)
target[datalength++] = Pad64;
else
target[datalength++] = Base64[output[2]];
target[datalength++] = Pad64;
}
if (datalength >= targsize)
return (-1);
target[datalength] = '\0'; /* Returned value doesn't count \0. */
return (datalength);
}
#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */
#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)
/* skips all whitespace anywhere.
converts characters, four at a time, starting at (or after)
src from base - 64 numbers into three 8 bit bytes in the target area.
it returns the number of data bytes stored at the target, or -1 on error.
*/
int
pamsshagentauth___b64_pton(char const *src, u_char *target, size_t targsize)
{
u_int tarindex, state;
int ch;
char *pos;
state = 0;
tarindex = 0;
while ((ch = *src++) != '\0') {
if (isspace(ch)) /* Skip whitespace anywhere. */
continue;
if (ch == Pad64)
break;
pos = strchr(Base64, ch);
if (pos == 0) /* A non-base64 character. */
return (-1);
switch (state) {
case 0:
if (target) {
if (tarindex >= targsize)
return (-1);
target[tarindex] = (pos - Base64) << 2;
}
state = 1;
break;
case 1:
if (target) {
if (tarindex + 1 >= targsize)
return (-1);
target[tarindex] |= (pos - Base64) >> 4;
target[tarindex+1] = ((pos - Base64) & 0x0f)
<< 4 ;
}
tarindex++;
state = 2;
break;
case 2:
if (target) {
if (tarindex + 1 >= targsize)
return (-1);
target[tarindex] |= (pos - Base64) >> 2;
target[tarindex+1] = ((pos - Base64) & 0x03)
<< 6;
}
tarindex++;
state = 3;
break;
case 3:
if (target) {
if (tarindex >= targsize)
return (-1);
target[tarindex] |= (pos - Base64);
}
tarindex++;
state = 0;
break;
}
}
/*
* We are done decoding Base-64 chars. Let's see if we ended
* on a byte boundary, and/or with erroneous trailing characters.
*/
if (ch == Pad64) { /* We got a pad char. */
ch = *src++; /* Skip it, get next. */
switch (state) {
case 0: /* Invalid = in first position */
case 1: /* Invalid = in second position */
return (-1);
case 2: /* Valid, means one byte of info */
/* Skip any number of spaces. */
for (; ch != '\0'; ch = *src++)
if (!isspace(ch))
break;
/* Make sure there is another trailing = sign. */
if (ch != Pad64)
return (-1);
ch = *src++; /* Skip the = */
/* Fall through to "single trailing =" case. */
/* FALLTHROUGH */
case 3: /* Valid, means two bytes of info */
/*
* We know this char is an =. Is there anything but
* whitespace after it?
*/
for (; ch != '\0'; ch = *src++)
if (!isspace(ch))
return (-1);
/*
* Now make sure for cases 2 and 3 that the "extra"
* bits that slopped past the last full byte were
* zeros. If we don't check them, they become a
* subliminal channel.
*/
if (target && target[tarindex] != 0)
return (-1);
}
} else {
/*
* We ended by seeing the end of the string. Make sure we
* have no partial bytes lying around.
*/
if (state != 0)
return (-1);
}
return (tarindex);
}
#endif /* !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) */
#endif

71
openbsd-compat/base64.h Normal file
View File

@ -0,0 +1,71 @@
/* $Id: base64.h,v 1.6 2003/08/29 16:59:52 mouring Exp $ */
/*
* Copyright (c) 1996 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/*
* Portions Copyright (c) 1995 by International Business Machines, Inc.
*
* International Business Machines, Inc. (hereinafter called IBM) grants
* permission under its copyrights to use, copy, modify, and distribute this
* Software with or without fee, provided that the above copyright notice and
* all paragraphs of this notice appear in all copies, and that the name of IBM
* not be used in connection with the marketing of any product incorporating
* the Software or modifications thereof, without specific, written prior
* permission.
*
* To the extent it has a right to do so, IBM grants an immunity from suit
* under its patents, if any, for the use, sale or manufacture of products to
* the extent that such products are used for performing Domain Name System
* dynamic updates in TCP/IP networks by means of the Software. No immunity is
* granted for any product per se or for any other function of any product.
*
* THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
* DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef _BSD_BASE64_H
#define _BSD_BASE64_H
#include "includes.h"
#ifndef HAVE___B64_NTOP
# ifndef HAVE_B64_NTOP
int pamsshagentauth___b64_ntop(u_char const *src, size_t srclength, char *target,
size_t targsize);
# else
# define __b64_ntop(a,b,c,d) b64_ntop(a,b,c,d)
# endif /* !HAVE_B64_NTOP */
#else
# define pamsshagentauth___b64_ntop(a,b,c,d) __b64_ntop(a,b,c,d)
#endif /* HAVE___B64_NTOP */
#ifndef HAVE___B64_PTON
# ifndef HAVE_B64_PTON
int pamsshagentauth___b64_pton(char const *src, u_char *target, size_t targsize);
# else
# define pamsshagentauth___b64_pton(a,b,c) b64_pton(a,b,c)
# endif /* !HAVE_B64_PTON */
#else
# define pamsshagentauth___b64_pton(a,b,c) __b64_pton(a,b,c)
#endif /* HAVE___B64_PTON */
#endif /* _BSD_BASE64_H */

67
openbsd-compat/basename.c Normal file
View File

@ -0,0 +1,67 @@
/* $OpenBSD: basename.c,v 1.14 2005/08/08 08:05:33 espie Exp $ */
/*
* Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* OPENBSD ORIGINAL: lib/libc/gen/basename.c */
#include "includes.h"
#ifndef HAVE_BASENAME
#include <errno.h>
#include <string.h>
char *
basename(const char *path)
{
static char bname[MAXPATHLEN];
size_t len;
const char *endp, *startp;
/* Empty or NULL string gets treated as "." */
if (path == NULL || *path == '\0') {
bname[0] = '.';
bname[1] = '\0';
return (bname);
}
/* Strip any trailing slashes */
endp = path + strlen(path) - 1;
while (endp > path && *endp == '/')
endp--;
/* All slashes becomes "/" */
if (endp == path && *endp == '/') {
bname[0] = '/';
bname[1] = '\0';
return (bname);
}
/* Find the start of the base */
startp = endp;
while (startp > path && *(startp - 1) != '/')
startp--;
len = endp - startp + 1;
if (len >= sizeof(bname)) {
errno = ENAMETOOLONG;
return (NULL);
}
memcpy(bname, startp, len);
bname[len] = '\0';
return (bname);
}
#endif /* !defined(HAVE_BASENAME) */

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 1999,2000,2004 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include <stdarg.h>
#include "log.h"
#ifndef HAVE_ARC4RANDOM
#include <openssl/rand.h>
#include <openssl/rc4.h>
#include <openssl/err.h>
/* Size of key to use */
#define SEED_SIZE 20
/* Number of bytes to reseed after */
#define REKEY_BYTES (1 << 24)
static int rc4_ready = 0;
static RC4_KEY rc4;
unsigned int
pamsshagentauth_arc4random(void)
{
unsigned int r = 0;
static int first_time = 1;
if (rc4_ready <= 0) {
if (first_time)
pamsshagentauth_seed_rng();
first_time = 0;
pamsshagentauth_arc4random_stir();
}
RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
rc4_ready -= sizeof(r);
return(r);
}
void
pamsshagentauth_arc4random_stir(void)
{
unsigned char rand_buf[SEED_SIZE];
int i;
memset(&rc4, 0, sizeof(rc4));
memset(&rand_buf, 0, sizeof(rand_buf));
if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0)
pamsshagentauth_fatal("Couldn't obtain random bytes (error %ld)",
ERR_get_error());
RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
/*
* Discard early keystream, as per recommendations in:
* http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
*/
for(i = 0; i <= 256; i += sizeof(rand_buf))
RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
memset(rand_buf, 0, sizeof(rand_buf));
rc4_ready = REKEY_BYTES;
}
#endif /* !HAVE_ARC4RANDOM */

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2004 Darren Tucker.
*
* Based originally on asprintf.c from OpenBSD:
* Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifndef HAVE_VASPRINTF
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#ifndef VA_COPY
# ifdef HAVE_VA_COPY
# define VA_COPY(dest, src) va_copy(dest, src)
# else
# ifdef HAVE___VA_COPY
# define VA_COPY(dest, src) __va_copy(dest, src)
# else
# define VA_COPY(dest, src) (dest) = (src)
# endif
# endif
#endif
#define INIT_SZ 128
int
vasprintf(char **str, const char *fmt, va_list ap)
{
int ret = -1;
va_list ap2;
char *string, *newstr;
size_t len;
VA_COPY(ap2, ap);
if ((string = malloc(INIT_SZ)) == NULL)
goto fail;
ret = vsnprintf(string, INIT_SZ, fmt, ap2);
if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */
*str = string;
} else if (ret == INT_MAX || ret < 0) { /* Bad length */
free(string);
goto fail;
} else { /* bigger than initial, realloc allowing for nul */
len = (size_t)ret + 1;
if ((newstr = realloc(string, len)) == NULL) {
free(string);
goto fail;
} else {
va_end(ap2);
VA_COPY(ap2, ap);
ret = vsnprintf(newstr, len, fmt, ap2);
if (ret >= 0 && (size_t)ret < len) {
*str = newstr;
} else { /* failed with realloc'ed string, give up */
free(newstr);
goto fail;
}
}
}
va_end(ap2);
return (ret);
fail:
*str = NULL;
errno = ENOMEM;
va_end(ap2);
return (-1);
}
#endif
#ifndef HAVE_ASPRINTF
int asprintf(char **str, const char *fmt, ...)
{
va_list ap;
int ret;
*str = NULL;
va_start(ap, fmt);
ret = vasprintf(str, fmt, ap);
va_end(ap);
return ret;
}
#endif

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2004-2005 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifndef HAVE_CLOSEFROM
#include <sys/types.h>
#include <sys/param.h>
#include <unistd.h>
#include <stdio.h>
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#include <limits.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#ifdef HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# ifdef HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# ifdef HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
#ifndef OPEN_MAX
# define OPEN_MAX 256
#endif
#if 0
__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $";
#endif /* lint */
/*
* Close all file descriptors greater than or equal to lowfd.
*/
#ifdef HAVE_FCNTL_CLOSEM
void
closefrom(int lowfd)
{
(void) fcntl(lowfd, F_CLOSEM, 0);
}
#else
void
closefrom(int lowfd)
{
long fd, maxfd;
#if defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
char fdpath[PATH_MAX], *endp;
struct dirent *dent;
DIR *dirp;
int len;
/* Check for a /proc/$$/fd directory. */
len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
if (len > 0 && (size_t)len <= sizeof(fdpath) && (dirp = opendir(fdpath))) {
while ((dent = readdir(dirp)) != NULL) {
fd = strtol(dent->d_name, &endp, 10);
if (dent->d_name != endp && *endp == '\0' &&
fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
(void) close((int) fd);
}
(void) closedir(dirp);
} else
#endif
{
/*
* Fall back on sysconf() or getdtablesize(). We avoid checking
* resource limits since it is possible to open a file descriptor
* and then drop the rlimit such that it is below the open fd.
*/
#ifdef HAVE_SYSCONF
maxfd = sysconf(_SC_OPEN_MAX);
#else
maxfd = getdtablesize();
#endif /* HAVE_SYSCONF */
if (maxfd < 0)
maxfd = OPEN_MAX;
for (fd = lowfd; fd < maxfd; fd++)
(void) close((int) fd);
}
}
#endif /* !HAVE_FCNTL_CLOSEM */
#endif /* HAVE_CLOSEFROM */

817
openbsd-compat/bsd-cray.c Normal file
View File

@ -0,0 +1,817 @@
/*
* $Id: bsd-cray.c,v 1.17 2007/08/15 09:17:43 dtucker Exp $
*
* bsd-cray.c
*
* Copyright (c) 2002, Cray Inc. (Wendy Palm <wendyp@cray.com>)
* Significant portions provided by
* Wayne Schroeder, SDSC <schroeder@sdsc.edu>
* William Jones, UTexas <jones@tacc.utexas.edu>
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* Created: Apr 22 16.34:00 2002 wp
*
* This file contains functions required for proper execution
* on UNICOS systems.
*
*/
#ifdef _UNICOS
#include <udb.h>
#include <tmpdir.h>
#include <unistd.h>
#include <sys/category.h>
#include <utmp.h>
#include <sys/jtab.h>
#include <signal.h>
#include <sys/priv.h>
#include <sys/secparm.h>
#include <sys/tfm.h>
#include <sys/usrv.h>
#include <sys/sysv.h>
#include <sys/sectab.h>
#include <sys/secstat.h>
#include <sys/stat.h>
#include <sys/session.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include <fcntl.h>
#include <errno.h>
#include <ia.h>
#include <urm.h>
#include "ssh.h"
#include "includes.h"
#include "sys/types.h"
#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
# define _SS_MAXSIZE 128 /* Implementation specific max size */
# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr))
# define ss_family ss_sa.sa_family
#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
#ifndef IN6_IS_ADDR_LOOPBACK
# define IN6_IS_ADDR_LOOPBACK(a) \
(((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \
((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1))
#endif /* !IN6_IS_ADDR_LOOPBACK */
#ifndef AF_INET6
/* Define it to something that should never appear */
#define AF_INET6 AF_MAX
#endif
#include "log.h"
#include "servconf.h"
#include "bsd-cray.h"
#define MAXACID 80
extern ServerOptions options;
char cray_tmpdir[TPATHSIZ + 1]; /* job TMPDIR path */
struct sysv sysv; /* system security structure */
struct usrv usrv; /* user security structure */
/*
* Functions.
*/
void cray_retain_utmp(struct utmp *, int);
void cray_delete_tmpdir(char *, int, uid_t);
void cray_init_job(struct passwd *);
void cray_set_tmpdir(struct utmp *);
void cray_login_failure(char *, int);
int cray_setup(uid_t, char *, const char *);
int cray_access_denied(char *);
void
cray_login_failure(char *username, int errcode)
{
struct udb *ueptr; /* UDB pointer for username */
ia_failure_t fsent; /* ia_failure structure */
ia_failure_ret_t fret; /* ia_failure return stuff */
struct jtab jtab; /* job table structure */
int jid = 0; /* job id */
if ((jid = getjtab(&jtab)) < 0)
pamsshagentauth_verbose("cray_login_failure(): getjtab error");
getsysudb();
if ((ueptr = getudbnam(username)) == UDB_NULL)
pamsshagentauth_verbose("cray_login_failure(): getudbname() returned NULL");
endudb();
memset(&fsent, '\0', sizeof(fsent));
fsent.revision = 0;
fsent.uname = username;
fsent.host = (char *)get_canonical_hostname(options.use_dns);
fsent.ttyn = "sshd";
fsent.caller = IA_SSHD;
fsent.flags = IA_INTERACTIVE;
fsent.ueptr = ueptr;
fsent.jid = jid;
fsent.errcode = errcode;
fsent.pwdp = NULL;
fsent.exitcode = 0; /* dont exit in ia_failure() */
fret.revision = 0;
fret.normal = 0;
/*
* Call ia_failure because of an login failure.
*/
ia_failure(&fsent, &fret);
}
/*
* Cray access denied
*/
int
cray_access_denied(char *username)
{
struct udb *ueptr; /* UDB pointer for username */
int errcode; /* IA errorcode */
errcode = 0;
getsysudb();
if ((ueptr = getudbnam(username)) == UDB_NULL)
pamsshagentauth_verbose("cray_login_failure(): getudbname() returned NULL");
endudb();
if (ueptr != NULL && ueptr->ue_disabled)
errcode = IA_DISABLED;
if (errcode)
cray_login_failure(username, errcode);
return (errcode);
}
/*
* record_failed_login: generic "login failed" interface function
*/
void
record_failed_login(const char *user, const char *hostname, const char *ttyname)
{
cray_login_failure((char *)user, IA_UDBERR);
}
int
cray_setup (uid_t uid, char *username, const char *command)
{
extern struct udb *getudb();
extern char *setlimits();
int err; /* error return */
time_t system_time; /* current system clock */
time_t expiration_time; /* password expiration time */
int maxattempts; /* maximum no. of failed login attempts */
int SecureSys; /* unicos security flag */
int minslevel = 0; /* system minimum security level */
int i, j;
int valid_acct = -1; /* flag for reading valid acct */
char acct_name[MAXACID] = { "" }; /* used to read acct name */
struct jtab jtab; /* Job table struct */
struct udb ue; /* udb entry for logging-in user */
struct udb *up; /* pointer to UDB entry */
struct secstat secinfo; /* file security attributes */
struct servprov init_info; /* used for sesscntl() call */
int jid; /* job ID */
int pid; /* process ID */
char *sr; /* status return from setlimits() */
char *ttyn = NULL; /* ttyname or command name*/
char hostname[MAXHOSTNAMELEN];
/* passwd stuff for ia_user */
passwd_t pwdacm, pwddialup, pwdudb, pwdwal, pwddce;
ia_user_ret_t uret; /* stuff returned from ia_user */
ia_user_t usent; /* ia_user main structure */
int ia_rcode; /* ia_user return code */
ia_failure_t fsent; /* ia_failure structure */
ia_failure_ret_t fret; /* ia_failure return stuff */
ia_success_t ssent; /* ia_success structure */
ia_success_ret_t sret; /* ia_success return stuff */
int ia_mlsrcode; /* ia_mlsuser return code */
int secstatrc; /* [f]secstat return code */
if (SecureSys = (int)sysconf(_SC_CRAY_SECURE_SYS)) {
getsysv(&sysv, sizeof(struct sysv));
minslevel = sysv.sy_minlvl;
if (getusrv(&usrv) < 0)
pamsshagentauth_fatal("getusrv() failed, errno = %d", errno);
}
hostname[0] = '\0';
pamsshagentauth_strlcpy(hostname,
(char *)get_canonical_hostname(options.use_dns),
MAXHOSTNAMELEN);
/*
* Fetch user's UDB entry.
*/
getsysudb();
if ((up = getudbnam(username)) == UDB_NULL)
pamsshagentauth_fatal("cannot fetch user's UDB entry");
/*
* Prevent any possible fudging so perform a data
* safety check and compare the supplied uid against
* the udb's uid.
*/
if (up->ue_uid != uid)
pamsshagentauth_fatal("IA uid missmatch");
endudb();
if ((jid = getjtab(&jtab)) < 0) {
pamsshagentauth_verbose("getjtab");
return(-1);
}
pid = getpid();
ttyn = ttyname(0);
if (SecureSys) {
if (ttyn != NULL)
secstatrc = secstat(ttyn, &secinfo);
else
secstatrc = fsecstat(1, &secinfo);
if (secstatrc == 0)
pamsshagentauth_verbose("[f]secstat() successful");
else
pamsshagentauth_fatal("[f]secstat() error, rc = %d", secstatrc);
}
if ((ttyn == NULL) && ((char *)command != NULL))
ttyn = (char *)command;
/*
* Initialize all structures to call ia_user
*/
usent.revision = 0;
usent.uname = username;
usent.host = hostname;
usent.ttyn = ttyn;
usent.caller = IA_SSHD;
usent.pswdlist = &pwdacm;
usent.ueptr = &ue;
usent.flags = IA_INTERACTIVE | IA_FFLAG;
pwdacm.atype = IA_SECURID;
pwdacm.pwdp = NULL;
pwdacm.next = &pwdudb;
pwdudb.atype = IA_UDB;
pwdudb.pwdp = NULL;
pwdudb.next = &pwddce;
pwddce.atype = IA_DCE;
pwddce.pwdp = NULL;
pwddce.next = &pwddialup;
pwddialup.atype = IA_DIALUP;
pwddialup.pwdp = NULL;
/* pwddialup.next = &pwdwal; */
pwddialup.next = NULL;
pwdwal.atype = IA_WAL;
pwdwal.pwdp = NULL;
pwdwal.next = NULL;
uret.revision = 0;
uret.pswd = NULL;
uret.normal = 0;
ia_rcode = ia_user(&usent, &uret);
switch (ia_rcode) {
/*
* These are acceptable return codes from ia_user()
*/
case IA_UDBWEEK: /* Password Expires in 1 week */
expiration_time = ue.ue_pwage.time + ue.ue_pwage.maxage;
printf ("WARNING - your current password will expire %s\n",
ctime((const time_t *)&expiration_time));
break;
case IA_UDBEXPIRED:
if (ttyname(0) != NULL) {
/* Force a password change */
printf("Your password has expired; Choose a new one.\n");
execl("/bin/passwd", "passwd", username, 0);
exit(9);
}
break;
case IA_NORMAL: /* Normal Return Code */
break;
case IA_BACKDOOR:
/* XXX: can we memset it to zero here so save some of this */
pamsshagentauth_strlcpy(ue.ue_name, "root", sizeof(ue.ue_name));
pamsshagentauth_strlcpy(ue.ue_dir, "/", sizeof(ue.ue_dir));
pamsshagentauth_strlcpy(ue.ue_shell, "/bin/sh", sizeof(ue.ue_shell));
ue.ue_passwd[0] = '\0';
ue.ue_age[0] = '\0';
ue.ue_comment[0] = '\0';
ue.ue_loghost[0] = '\0';
ue.ue_logline[0] = '\0';
ue.ue_uid = -1;
ue.ue_nice[UDBRC_INTER] = 0;
for (i = 0; i < MAXVIDS; i++)
ue.ue_gids[i] = 0;
ue.ue_logfails = 0;
ue.ue_minlvl = ue.ue_maxlvl = ue.ue_deflvl = minslevel;
ue.ue_defcomps = 0;
ue.ue_comparts = 0;
ue.ue_permits = 0;
ue.ue_trap = 0;
ue.ue_disabled = 0;
ue.ue_logtime = 0;
break;
case IA_CONSOLE: /* Superuser not from Console */
case IA_TRUSTED: /* Trusted user */
if (options.permit_root_login > PERMIT_NO)
break; /* Accept root login */
default:
/*
* These are failed return codes from ia_user()
*/
switch (ia_rcode)
{
case IA_BADAUTH:
printf("Bad authorization, access denied.\n");
break;
case IA_DISABLED:
printf("Your login has been disabled. Contact the system ");
printf("administrator for assistance.\n");
break;
case IA_GETSYSV:
printf("getsysv() failed - errno = %d\n", errno);
break;
case IA_MAXLOGS:
printf("Maximum number of failed login attempts exceeded.\n");
printf("Access denied.\n");
break;
case IA_UDBPWDNULL:
if (SecureSys)
printf("NULL Password not allowed on MLS systems.\n");
break;
default:
break;
}
/*
* Authentication failed.
*/
printf("sshd: Login incorrect, (0%o)\n",
ia_rcode-IA_ERRORCODE);
/*
* Initialize structure for ia_failure
* which will exit.
*/
fsent.revision = 0;
fsent.uname = username;
fsent.host = hostname;
fsent.ttyn = ttyn;
fsent.caller = IA_SSHD;
fsent.flags = IA_INTERACTIVE;
fsent.ueptr = &ue;
fsent.jid = jid;
fsent.errcode = ia_rcode;
fsent.pwdp = uret.pswd;
fsent.exitcode = 1;
fret.revision = 0;
fret.normal = 0;
/*
* Call ia_failure because of an IA failure.
* There is no return because ia_failure exits.
*/
ia_failure(&fsent, &fret);
exit(1);
}
ia_mlsrcode = IA_NORMAL;
if (SecureSys) {
pamsshagentauth_verbose("calling ia_mlsuser()");
ia_mlsrcode = ia_mlsuser(&ue, &secinfo, &usrv, NULL, 0);
}
if (ia_mlsrcode != IA_NORMAL) {
printf("sshd: Login incorrect, (0%o)\n",
ia_mlsrcode-IA_ERRORCODE);
/*
* Initialize structure for ia_failure
* which will exit.
*/
fsent.revision = 0;
fsent.uname = username;
fsent.host = hostname;
fsent.ttyn = ttyn;
fsent.caller = IA_SSHD;
fsent.flags = IA_INTERACTIVE;
fsent.ueptr = &ue;
fsent.jid = jid;
fsent.errcode = ia_mlsrcode;
fsent.pwdp = uret.pswd;
fsent.exitcode = 1;
fret.revision = 0;
fret.normal = 0;
/*
* Call ia_failure because of an IA failure.
* There is no return because ia_failure exits.
*/
ia_failure(&fsent,&fret);
exit(1);
}
/* Provide login status information */
if (options.print_lastlog && ue.ue_logtime != 0) {
printf("Last successful login was : %.*s ", 19,
(char *)ctime(&ue.ue_logtime));
if (*ue.ue_loghost != '\0') {
printf("from %.*s\n", sizeof(ue.ue_loghost),
ue.ue_loghost);
} else {
printf("on %.*s\n", sizeof(ue.ue_logline),
ue.ue_logline);
}
if (SecureSys && (ue.ue_logfails != 0)) {
printf(" followed by %d failed attempts\n",
ue.ue_logfails);
}
}
/*
* Call ia_success to process successful I/A.
*/
ssent.revision = 0;
ssent.uname = username;
ssent.host = hostname;
ssent.ttyn = ttyn;
ssent.caller = IA_SSHD;
ssent.flags = IA_INTERACTIVE;
ssent.ueptr = &ue;
ssent.jid = jid;
ssent.errcode = ia_rcode;
ssent.us = NULL;
ssent.time = 1; /* Set ue_logtime */
sret.revision = 0;
sret.normal = 0;
ia_success(&ssent, &sret);
/*
* Query for account, iff > 1 valid acid & askacid permbit
*/
if (((ue.ue_permbits & PERMBITS_ACCTID) ||
(ue.ue_acids[0] >= 0) && (ue.ue_acids[1] >= 0)) &&
ue.ue_permbits & PERMBITS_ASKACID) {
if (ttyname(0) != NULL) {
pamsshagentauth_verbose("cray_setup: ttyname true case, %.100s", ttyname);
while (valid_acct == -1) {
printf("Account (? for available accounts)"
" [%s]: ", acid2nam(ue.ue_acids[0]));
fgets(acct_name, MAXACID, stdin);
switch (acct_name[0]) {
case EOF:
exit(0);
break;
case '\0':
valid_acct = ue.ue_acids[0];
pamsshagentauth_strlcpy(acct_name, acid2nam(valid_acct), MAXACID);
break;
case '?':
/* Print the list 3 wide */
for (i = 0, j = 0; i < MAXVIDS; i++) {
if (ue.ue_acids[i] == -1) {
printf("\n");
break;
}
if (++j == 4) {
j = 1;
printf("\n");
}
printf(" %s",
acid2nam(ue.ue_acids[i]));
}
if (ue.ue_permbits & PERMBITS_ACCTID) {
printf("\"acctid\" permbit also allows"
" you to select any valid "
"account name.\n");
}
printf("\n");
break;
default:
valid_acct = nam2acid(acct_name);
if (valid_acct == -1)
printf(
"Account id not found for"
" account name \"%s\"\n\n",
acct_name);
break;
}
/*
* If an account was given, search the user's
* acids array to verify they can use this account.
*/
if ((valid_acct != -1) &&
!(ue.ue_permbits & PERMBITS_ACCTID)) {
for (i = 0; i < MAXVIDS; i++) {
if (ue.ue_acids[i] == -1)
break;
if (valid_acct == ue.ue_acids[i])
break;
}
if (i == MAXVIDS ||
ue.ue_acids[i] == -1) {
fprintf(stderr, "Cannot set"
" account name to "
"\"%s\", permission "
"denied\n\n", acct_name);
valid_acct = -1;
}
}
}
} else {
/*
* The client isn't connected to a terminal and can't
* respond to an acid prompt. Use default acid.
*/
pamsshagentauth_verbose("cray_setup: ttyname false case, %.100s",
ttyname);
valid_acct = ue.ue_acids[0];
}
} else {
/*
* The user doesn't have the askacid permbit set or
* only has one valid account to use.
*/
valid_acct = ue.ue_acids[0];
}
if (acctid(0, valid_acct) < 0) {
printf ("Bad account id: %d\n", valid_acct);
exit(1);
}
/*
* Now set shares, quotas, limits, including CPU time for the
* (interactive) job and process, and set up permissions
* (for chown etc), etc.
*/
if (setshares(ue.ue_uid, valid_acct, printf, 0, 0)) {
printf("Unable to give %d shares to <%s>(%d/%d)\n",
ue.ue_shares, ue.ue_name, ue.ue_uid, valid_acct);
exit(1);
}
sr = setlimits(username, C_PROC, pid, UDBRC_INTER);
if (sr != NULL) {
pamsshagentauth_verbose("%.200s", sr);
exit(1);
}
sr = setlimits(username, C_JOB, jid, UDBRC_INTER);
if (sr != NULL) {
pamsshagentauth_verbose("%.200s", sr);
exit(1);
}
/*
* Place the service provider information into
* the session table (Unicos) or job table (Unicos/mk).
* There exist double defines for the job/session table in
* unicos/mk (jtab.h) so no need for a compile time switch.
*/
memset(&init_info, '\0', sizeof(init_info));
init_info.s_sessinit.si_id = URM_SPT_LOGIN;
init_info.s_sessinit.si_pid = getpid();
init_info.s_sessinit.si_sid = jid;
sesscntl(0, S_SETSERVPO, (int)&init_info);
/*
* Set user and controlling tty security attributes.
*/
if (SecureSys) {
if (setusrv(&usrv) == -1) {
pamsshagentauth_verbose("setusrv() failed, errno = %d",errno);
exit(1);
}
}
return (0);
}
/*
* The rc.* and /etc/sdaemon methods of starting a program on unicos/unicosmk
* can have pal privileges that sshd can inherit which
* could allow a user to su to root with out a password.
* This subroutine clears all privileges.
*/
void
drop_cray_privs()
{
#if defined(_SC_CRAY_PRIV_SU)
priv_proc_t *privstate;
int result;
extern int priv_set_proc();
extern priv_proc_t *priv_init_proc();
/*
* If ether of theses two flags are not set
* then don't allow this version of ssh to run.
*/
if (!sysconf(_SC_CRAY_PRIV_SU))
pamsshagentauth_fatal("Not PRIV_SU system.");
if (!sysconf(_SC_CRAY_POSIX_PRIV))
pamsshagentauth_fatal("Not POSIX_PRIV.");
pamsshagentauth_verbose("Setting MLS labels.");;
if (sysconf(_SC_CRAY_SECURE_MAC)) {
usrv.sv_minlvl = SYSLOW;
usrv.sv_actlvl = SYSHIGH;
usrv.sv_maxlvl = SYSHIGH;
} else {
usrv.sv_minlvl = sysv.sy_minlvl;
usrv.sv_actlvl = sysv.sy_minlvl;
usrv.sv_maxlvl = sysv.sy_maxlvl;
}
usrv.sv_actcmp = 0;
usrv.sv_valcmp = sysv.sy_valcmp;
usrv.sv_intcat = TFM_SYSTEM;
usrv.sv_valcat |= (TFM_SYSTEM | TFM_SYSFILE);
if (setusrv(&usrv) < 0) {
pamsshagentauth_fatal("%s(%d): setusrv(): %s", __FILE__, __LINE__,
strerror(errno));
}
if ((privstate = priv_init_proc()) != NULL) {
result = priv_set_proc(privstate);
if (result != 0 ) {
pamsshagentauth_fatal("%s(%d): priv_set_proc(): %s",
__FILE__, __LINE__, strerror(errno));
}
priv_free_proc(privstate);
}
verbose ("Privileges should be cleared...");
#else
/* XXX: do this differently */
# error Cray systems must be run with _SC_CRAY_PRIV_SU on!
#endif
}
/*
* Retain utmp/wtmp information - used by cray accounting.
*/
void
cray_retain_utmp(struct utmp *ut, int pid)
{
int fd;
struct utmp utmp;
if ((fd = open(UTMP_FILE, O_RDONLY)) != -1) {
/* XXX use atomicio */
while (read(fd, (char *)&utmp, sizeof(utmp)) == sizeof(utmp)) {
if (pid == utmp.ut_pid) {
ut->ut_jid = utmp.ut_jid;
strncpy(ut->ut_tpath, utmp.ut_tpath, sizeof(utmp.ut_tpath));
strncpy(ut->ut_host, utmp.ut_host, sizeof(utmp.ut_host));
strncpy(ut->ut_name, utmp.ut_name, sizeof(utmp.ut_name));
break;
}
}
close(fd);
} else
pamsshagentauth_fatal("Unable to open utmp file");
}
/*
* tmpdir support.
*/
/*
* find and delete jobs tmpdir.
*/
void
cray_delete_tmpdir(char *login, int jid, uid_t uid)
{
static char jtmp[TPATHSIZ];
struct stat statbuf;
int child, c, wstat;
for (c = 'a'; c <= 'z'; c++) {
snprintf(jtmp, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c);
if (stat(jtmp, &statbuf) == 0 && statbuf.st_uid == uid)
break;
}
if (c > 'z')
return;
if ((child = fork()) == 0) {
execl(CLEANTMPCMD, CLEANTMPCMD, login, jtmp, (char *)NULL);
pamsshagentauth_fatal("cray_delete_tmpdir: execl of CLEANTMPCMD failed");
}
while (waitpid(child, &wstat, 0) == -1 && errno == EINTR)
;
}
/*
* Remove tmpdir on job termination.
*/
void
cray_job_termination_handler(int sig)
{
int jid;
char *login = NULL;
struct jtab jtab;
if ((jid = waitjob(&jtab)) == -1 ||
(login = uid2nam(jtab.j_uid)) == NULL)
return;
cray_delete_tmpdir(login, jid, jtab.j_uid);
}
/*
* Set job id and create tmpdir directory.
*/
void
cray_init_job(struct passwd *pw)
{
int jid;
int c;
jid = setjob(pw->pw_uid, WJSIGNAL);
if (jid < 0)
pamsshagentauth_fatal("System call setjob failure");
for (c = 'a'; c <= 'z'; c++) {
snprintf(cray_tmpdir, TPATHSIZ, "%s/jtmp.%06d%c", JTMPDIR, jid, c);
if (mkdir(cray_tmpdir, JTMPMODE) != 0)
continue;
if (chown(cray_tmpdir, pw->pw_uid, pw->pw_gid) != 0) {
rmdir(cray_tmpdir);
continue;
}
break;
}
if (c > 'z')
cray_tmpdir[0] = '\0';
}
void
cray_set_tmpdir(struct utmp *ut)
{
int jid;
struct jtab jbuf;
if ((jid = getjtab(&jbuf)) < 0)
return;
/*
* Set jid and tmpdir in utmp record.
*/
ut->ut_jid = jid;
strncpy(ut->ut_tpath, cray_tmpdir, TPATHSIZ);
}
#endif /* UNICOS */
#ifdef _UNICOSMP
#include <pwd.h>
/*
* Set job id and create tmpdir directory.
*/
void
cray_init_job(struct passwd *pw)
{
initrm_silent(pw->pw_uid);
return;
}
#endif /* _UNICOSMP */

61
openbsd-compat/bsd-cray.h Normal file
View File

@ -0,0 +1,61 @@
/* $Id: bsd-cray.h,v 1.12 2005/02/02 06:10:11 dtucker Exp $ */
/*
* Copyright (c) 2002, Cray Inc. (Wendy Palm <wendyp@cray.com>)
* Significant portions provided by
* Wayne Schroeder, SDSC <schroeder@sdsc.edu>
* William Jones, UTexas <jones@tacc.utexas.edu>
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* Created: Apr 22 16.34:00 2002 wp
*
* This file contains functions required for proper execution
* on UNICOS systems.
*
*/
#ifndef _BSD_CRAY_H
#define _BSD_CRAY_H
#ifdef _UNICOS
void cray_init_job(struct passwd *);
void cray_job_termination_handler(int);
void cray_login_failure(char *, int );
int cray_access_denied(char *);
extern char cray_tmpdir[];
#define CUSTOM_FAILED_LOGIN 1
#ifndef IA_SSHD
# define IA_SSHD IA_LOGIN
#endif
#ifndef MAXHOSTNAMELEN
# define MAXHOSTNAMELEN 64
#endif
#ifndef _CRAYT3E
# define TIOCGPGRP (tIOC|20)
#endif
#endif /* UNICOS */
#endif /* _BSD_CRAY_H */

View File

@ -0,0 +1,293 @@
/*
* Copyright (c) 2000, 2001, Corinna Vinschen <vinschen@cygnus.com>
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* Created: Sat Sep 02 12:17:00 2000 cv
*
* This file contains functions for forcing opened file descriptors to
* binary mode on Windows systems.
*/
#include "includes.h"
#ifdef HAVE_CYGWIN
#if defined(open) && open == binary_open
# undef open
#endif
#if defined(pipe) && open == binary_pipe
# undef pipe
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <sys/vfs.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <windows.h>
#include "xmalloc.h"
#define is_winnt (GetVersion() < 0x80000000)
#define ntsec_on(c) ((c) && strstr((c),"ntsec") && !strstr((c),"nontsec"))
#define ntsec_off(c) ((c) && strstr((c),"nontsec"))
#define ntea_on(c) ((c) && strstr((c),"ntea") && !strstr((c),"nontea"))
int
binary_open(const char *filename, int flags, ...)
{
va_list ap;
mode_t mode;
va_start(ap, flags);
mode = va_arg(ap, mode_t);
va_end(ap);
return (open(filename, flags | O_BINARY, mode));
}
int
binary_pipe(int fd[2])
{
int ret = pipe(fd);
if (!ret) {
setmode(fd[0], O_BINARY);
setmode(fd[1], O_BINARY);
}
return (ret);
}
#define HAS_CREATE_TOKEN 1
#define HAS_NTSEC_BY_DEFAULT 2
#define HAS_CREATE_TOKEN_WO_NTSEC 3
static int
has_capability(int what)
{
static int inited;
static int has_create_token;
static int has_ntsec_by_default;
static int has_create_token_wo_ntsec;
/*
* has_capability() basically calls uname() and checks if
* specific capabilities of Cygwin can be evaluated from that.
* This simplifies the calling functions which only have to ask
* for a capability using has_capability() instead of having
* to figure that out by themselves.
*/
if (!inited) {
struct utsname uts;
if (!uname(&uts)) {
int major_high = 0, major_low = 0, minor = 0;
int api_major_version = 0, api_minor_version = 0;
char *c;
sscanf(uts.release, "%d.%d.%d", &major_high,
&major_low, &minor);
if ((c = strchr(uts.release, '(')) != NULL) {
sscanf(c + 1, "%d.%d", &api_major_version,
&api_minor_version);
}
if (major_high > 1 ||
(major_high == 1 && (major_low > 3 ||
(major_low == 3 && minor >= 2))))
has_create_token = 1;
if (api_major_version > 0 || api_minor_version >= 56)
has_ntsec_by_default = 1;
if (major_high > 1 ||
(major_high == 1 && major_low >= 5))
has_create_token_wo_ntsec = 1;
inited = 1;
}
}
switch (what) {
case HAS_CREATE_TOKEN:
return (has_create_token);
case HAS_NTSEC_BY_DEFAULT:
return (has_ntsec_by_default);
case HAS_CREATE_TOKEN_WO_NTSEC:
return (has_create_token_wo_ntsec);
}
return (0);
}
int
check_nt_auth(int pwd_authenticated, struct passwd *pw)
{
/*
* The only authentication which is able to change the user
* context on NT systems is the password authentication. So
* we deny all requsts for changing the user context if another
* authentication method is used.
*
* This doesn't apply to Cygwin versions >= 1.3.2 anymore which
* uses the undocumented NtCreateToken() call to create a user
* token if the process has the appropriate privileges and if
* CYGWIN ntsec setting is on.
*/
static int has_create_token = -1;
if (pw == NULL)
return 0;
if (is_winnt) {
if (has_create_token < 0) {
char *cygwin = getenv("CYGWIN");
has_create_token = 0;
if (has_capability(HAS_CREATE_TOKEN) &&
(ntsec_on(cygwin) ||
(has_capability(HAS_NTSEC_BY_DEFAULT) &&
!ntsec_off(cygwin)) ||
has_capability(HAS_CREATE_TOKEN_WO_NTSEC)))
has_create_token = 1;
}
if (has_create_token < 1 &&
!pwd_authenticated && geteuid() != pw->pw_uid)
return (0);
}
return (1);
}
int
check_ntsec(const char *filename)
{
char *cygwin;
int allow_ntea = 0, allow_ntsec = 0;
struct statfs fsstat;
/* Windows 95/98/ME don't support file system security at all. */
if (!is_winnt)
return (0);
/* Evaluate current CYGWIN settings. */
cygwin = getenv("CYGWIN");
allow_ntea = ntea_on(cygwin);
allow_ntsec = ntsec_on(cygwin) ||
(has_capability(HAS_NTSEC_BY_DEFAULT) && !ntsec_off(cygwin));
/*
* `ntea' is an emulation of POSIX attributes. It doesn't support
* real file level security as ntsec on NTFS file systems does
* but it supports FAT filesystems. `ntea' is minimum requirement
* for security checks.
*/
if (allow_ntea)
return (1);
/*
* Retrieve file system flags. In Cygwin, file system flags are
* copied to f_type which has no meaning in Win32 itself.
*/
if (statfs(filename, &fsstat))
return (1);
/*
* Only file systems supporting ACLs are able to set permissions.
* `ntsec' is the setting in Cygwin which switches using of NTFS
* ACLs to support POSIX permissions on files.
*/
if (fsstat.f_type & FS_PERSISTENT_ACLS)
return (allow_ntsec);
return (0);
}
void
register_9x_service(void)
{
HINSTANCE kerneldll;
DWORD (*RegisterServiceProcess)(DWORD, DWORD);
/* The service register mechanism in 9x/Me is pretty different from
* NT/2K/XP. In NT/2K/XP we're using a special service starter
* application to register and control sshd as service. This method
* doesn't play nicely with 9x/Me. For that reason we register here
* as service when running under 9x/Me. This function is only called
* by the child sshd when it's going to daemonize.
*/
if (is_winnt)
return;
if (!(kerneldll = LoadLibrary("KERNEL32.DLL")))
return;
if (!(RegisterServiceProcess = (DWORD (*)(DWORD, DWORD))
GetProcAddress(kerneldll, "RegisterServiceProcess")))
return;
RegisterServiceProcess(0, 1);
}
#define NL(x) x, (sizeof (x) - 1)
#define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0]))
static struct wenv {
const char *name;
size_t namelen;
} wenv_arr[] = {
{ NL("ALLUSERSPROFILE=") },
{ NL("COMMONPROGRAMFILES=") },
{ NL("COMPUTERNAME=") },
{ NL("COMSPEC=") },
{ NL("CYGWIN=") },
{ NL("NUMBER_OF_PROCESSORS=") },
{ NL("OS=") },
{ NL("PATH=") },
{ NL("PATHEXT=") },
{ NL("PROCESSOR_ARCHITECTURE=") },
{ NL("PROCESSOR_IDENTIFIER=") },
{ NL("PROCESSOR_LEVEL=") },
{ NL("PROCESSOR_REVISION=") },
{ NL("PROGRAMFILES=") },
{ NL("SYSTEMDRIVE=") },
{ NL("SYSTEMROOT=") },
{ NL("TMP=") },
{ NL("TEMP=") },
{ NL("WINDIR=") }
};
char **
fetch_windows_environment(void)
{
char **e, **p;
unsigned int i, idx = 0;
p = pamsshagentauth_xcalloc(WENV_SIZ + 1, sizeof(char *));
for (e = environ; *e != NULL; ++e) {
for (i = 0; i < WENV_SIZ; ++i) {
if (!strncmp(*e, wenv_arr[i].name, wenv_arr[i].namelen))
p[idx++] = *e;
}
}
p[idx] = NULL;
return p;
}
void
free_windows_environment(char **p)
{
pamsshagentauth_xfree(p);
}
#endif /* HAVE_CYGWIN */

View File

@ -0,0 +1,57 @@
/* $Id: bsd-cygwin_util.h,v 1.11 2004/08/30 10:42:08 dtucker Exp $ */
/*
* Copyright (c) 2000, 2001, Corinna Vinschen <vinschen@cygnus.com>
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* Created: Sat Sep 02 12:17:00 2000 cv
*
* This file contains functions for forcing opened file descriptors to
* binary mode on Windows systems.
*/
#ifndef _BSD_CYGWIN_UTIL_H
#define _BSD_CYGWIN_UTIL_H
#ifdef HAVE_CYGWIN
#undef ERROR
#define is_winnt (GetVersion() < 0x80000000)
#include <windows.h>
#include <sys/cygwin.h>
#include <io.h>
int binary_open(const char *, int , ...);
int binary_pipe(int fd[2]);
int check_nt_auth(int, struct passwd *);
int check_ntsec(const char *);
void register_9x_service(void);
char **fetch_windows_environment(void);
void free_windows_environment(char **);
#define open binary_open
#define pipe binary_pipe
#endif /* HAVE_CYGWIN */
#endif /* _BSD_CYGWIN_UTIL_H */

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2002,2004 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#if !defined(HAVE_GETPEEREID)
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#if defined(SO_PEERCRED)
int
getpeereid(int s, uid_t *euid, gid_t *gid)
{
struct ucred cred;
socklen_t len = sizeof(cred);
if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cred, &len) < 0)
return (-1);
*euid = cred.uid;
*gid = cred.gid;
return (0);
}
#elif defined(HAVE_GETPEERUCRED)
#ifdef HAVE_UCRED_H
# include <ucred.h>
#endif
int
getpeereid(int s, uid_t *euid, gid_t *gid)
{
ucred_t *ucred = NULL;
if (getpeerucred(s, &ucred) == -1)
return (-1);
if ((*euid = ucred_geteuid(ucred)) == -1)
return (-1);
if ((*gid = ucred_getrgid(ucred)) == -1)
return (-1);
ucred_free(ucred);
return (0);
}
#else
int
getpeereid(int s, uid_t *euid, gid_t *gid)
{
*euid = geteuid();
*gid = getgid();
return (0);
}
#endif /* defined(SO_PEERCRED) */
#endif /* !defined(HAVE_GETPEEREID) */

245
openbsd-compat/bsd-misc.c Normal file
View File

@ -0,0 +1,245 @@
/*
* Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include "xmalloc.h"
#define UNUSED(expr) do { (void)(expr); } while (0)
#ifndef HAVE___PROGNAME
char *__progname;
#endif
/*
* NB. duplicate __progname in case it is an alias for argv[0]
* Otherwise it may get clobbered by setproctitle()
*/
char *ssh_get_progname(char *argv0)
{
#ifdef HAVE___PROGNAME
extern char *__progname;
UNUSED(argv0);
return pamsshagentauth_xstrdup(__progname);
#else
char *p;
if (argv0 == NULL)
return ("unknown"); /* XXX */
p = strrchr(argv0, '/');
if (p == NULL)
p = argv0;
else
p++;
return (pamsshagentauth_xstrdup(p));
#endif
}
#ifndef HAVE_SETLOGIN
int setlogin(const char *name)
{
UNUSED(name);
return (0);
}
#endif /* !HAVE_SETLOGIN */
#ifndef HAVE_INNETGR
int innetgr(const char *netgroup, const char *host,
const char *user, const char *domain)
{
return (0);
}
#endif /* HAVE_INNETGR */
#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
int seteuid(uid_t euid)
{
return (setreuid(-1, euid));
}
#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */
#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID)
int setegid(uid_t egid)
{
return(setresgid(-1, egid, -1));
}
#endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */
#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR)
const char *strerror(int e)
{
extern int sys_nerr;
extern char *sys_errlist[];
if ((e >= 0) && (e < sys_nerr))
return (sys_errlist[e]);
return ("unlisted error");
}
#endif
#ifndef HAVE_UTIMES
int utimes(char *filename, struct timeval *tvp)
{
struct utimbuf ub;
ub.actime = tvp[0].tv_sec;
ub.modtime = tvp[1].tv_sec;
return (utime(filename, &ub));
}
#endif
#ifndef HAVE_TRUNCATE
int truncate(const char *path, off_t length)
{
int fd, ret, saverrno;
fd = open(path, O_WRONLY);
if (fd < 0)
return (-1);
ret = ftruncate(fd, length);
saverrno = errno;
close(fd);
if (ret == -1)
errno = saverrno;
return(ret);
}
#endif /* HAVE_TRUNCATE */
#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP)
int nanosleep(const struct timespec *req, struct timespec *rem)
{
int rc, saverrno;
extern int errno;
struct timeval tstart, tstop, tremain, time2wait;
TIMESPEC_TO_TIMEVAL(&time2wait, req)
(void) gettimeofday(&tstart, NULL);
rc = select(0, NULL, NULL, NULL, &time2wait);
if (rc == -1) {
saverrno = errno;
(void) gettimeofday (&tstop, NULL);
errno = saverrno;
tremain.tv_sec = time2wait.tv_sec -
(tstop.tv_sec - tstart.tv_sec);
tremain.tv_usec = time2wait.tv_usec -
(tstop.tv_usec - tstart.tv_usec);
tremain.tv_sec += tremain.tv_usec / 1000000L;
tremain.tv_usec %= 1000000L;
} else {
tremain.tv_sec = 0;
tremain.tv_usec = 0;
}
if (rem != NULL)
TIMEVAL_TO_TIMESPEC(&tremain, rem)
return(rc);
}
#endif
#ifndef HAVE_TCGETPGRP
pid_t
tcgetpgrp(int fd)
{
int ctty_pgrp;
if (ioctl(fd, TIOCGPGRP, &ctty_pgrp) == -1)
return(-1);
else
return(ctty_pgrp);
}
#endif /* HAVE_TCGETPGRP */
#ifndef HAVE_TCSENDBREAK
int
tcsendbreak(int fd, int duration)
{
# if defined(TIOCSBRK) && defined(TIOCCBRK)
struct timeval sleepytime;
sleepytime.tv_sec = 0;
sleepytime.tv_usec = 400000;
if (ioctl(fd, TIOCSBRK, 0) == -1)
return (-1);
(void)select(0, 0, 0, 0, &sleepytime);
if (ioctl(fd, TIOCCBRK, 0) == -1)
return (-1);
return (0);
# else
return -1;
# endif
}
#endif /* HAVE_TCSENDBREAK */
mysig_t
mysignal(int sig, mysig_t act)
{
#ifdef HAVE_SIGACTION
struct sigaction sa, osa;
if (sigaction(sig, NULL, &osa) == -1)
return (mysig_t) -1;
if (osa.sa_handler != act) {
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
#ifdef SA_INTERRUPT
if (sig == SIGALRM)
sa.sa_flags |= SA_INTERRUPT;
#endif
sa.sa_handler = act;
if (sigaction(sig, &sa, NULL) == -1)
return (mysig_t) -1;
}
return (osa.sa_handler);
#else
#undef signal
return (signal(sig, act));
#endif
}
#ifndef HAVE_STRDUP
char *
strdup(const char *str)
{
size_t len;
char *cp;
len = strlen(str) + 1;
cp = malloc(len);
if (cp != NULL)
return(memcpy(cp, str, len));
return NULL;
}
#endif

98
openbsd-compat/bsd-misc.h Normal file
View File

@ -0,0 +1,98 @@
/* $Id: bsd-misc.h,v 1.18 2005/02/25 23:07:38 dtucker Exp $ */
/*
* Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BSD_MISC_H
#define _BSD_MISC_H
#include "includes.h"
char *ssh_get_progname(char *);
#ifndef HAVE_SETSID
#define setsid() setpgrp(0, getpid())
#endif /* !HAVE_SETSID */
#ifndef HAVE_SETENV
int setenv(const char *, const char *, int);
#endif /* !HAVE_SETENV */
#ifndef HAVE_SETLOGIN
int setlogin(const char *);
#endif /* !HAVE_SETLOGIN */
#ifndef HAVE_INNETGR
int innetgr(const char *, const char *, const char *, const char *);
#endif /* HAVE_INNETGR */
#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
int seteuid(uid_t);
#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */
#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID)
int setegid(uid_t);
#endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */
#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR)
const char *strerror(int);
#endif
#ifndef HAVE_UTIMES
#ifndef HAVE_STRUCT_TIMEVAL
struct timeval {
long tv_sec;
long tv_usec;
}
#endif /* HAVE_STRUCT_TIMEVAL */
int utimes(char *, struct timeval *);
#endif /* HAVE_UTIMES */
#ifndef HAVE_TRUNCATE
int truncate (const char *, off_t);
#endif /* HAVE_TRUNCATE */
#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP)
#ifndef HAVE_STRUCT_TIMESPEC
struct timespec {
time_t tv_sec;
long tv_nsec;
};
#endif
int nanosleep(const struct timespec *, struct timespec *);
#endif
#ifndef HAVE_TCGETPGRP
pid_t tcgetpgrp(int);
#endif
#ifndef HAVE_TCSENDBREAK
int tcsendbreak(int, int);
#endif
#ifndef HAVE_UNSETENV
void unsetenv(const char *);
#endif
/* wrapper for signal interface */
typedef void (*mysig_t)(int);
mysig_t mysignal(int sig, mysig_t act);
#define signal(a,b) mysignal(a,b)
#endif /* _BSD_MISC_H */

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2000,2001 Ben Lindstrom. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "includes.h"
#ifdef HAVE_NEXT
#include <errno.h>
#include <sys/wait.h>
#include "bsd-nextstep.h"
pid_t
posix_wait(int *status)
{
union wait statusp;
pid_t wait_pid;
#undef wait /* Use NeXT's wait() function */
wait_pid = wait(&statusp);
if (status)
*status = (int) statusp.w_status;
return (wait_pid);
}
int
tcgetattr(int fd, struct termios *t)
{
return (ioctl(fd, TIOCGETA, t));
}
int
tcsetattr(int fd, int opt, const struct termios *t)
{
struct termios localterm;
if (opt & TCSASOFT) {
localterm = *t;
localterm.c_cflag |= CIGNORE;
t = &localterm;
}
switch (opt & ~TCSASOFT) {
case TCSANOW:
return (ioctl(fd, TIOCSETA, t));
case TCSADRAIN:
return (ioctl(fd, TIOCSETAW, t));
case TCSAFLUSH:
return (ioctl(fd, TIOCSETAF, t));
default:
errno = EINVAL;
return (-1);
}
}
int tcsetpgrp(int fd, pid_t pgrp)
{
return (ioctl(fd, TIOCSPGRP, &pgrp));
}
speed_t cfgetospeed(const struct termios *t)
{
return (t->c_ospeed);
}
speed_t cfgetispeed(const struct termios *t)
{
return (t->c_ispeed);
}
int
cfsetospeed(struct termios *t,int speed)
{
t->c_ospeed = speed;
return (0);
}
int
cfsetispeed(struct termios *t, int speed)
{
t->c_ispeed = speed;
return (0);
}
#endif /* HAVE_NEXT */

View File

@ -0,0 +1,59 @@
/* $Id: bsd-nextstep.h,v 1.9 2003/08/29 16:59:52 mouring Exp $ */
/*
* Copyright (c) 2000,2001 Ben Lindstrom. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _NEXT_POSIX_H
#define _NEXT_POSIX_H
#ifdef HAVE_NEXT
#include <sys/dir.h>
/* NGROUPS_MAX is behind -lposix. Use the BSD version which is NGROUPS */
#undef NGROUPS_MAX
#define NGROUPS_MAX NGROUPS
/* NeXT's readdir() is BSD (struct direct) not POSIX (struct dirent) */
#define dirent direct
/* Swap out NeXT's BSD wait() for a more POSIX complient one */
pid_t posix_wait(int *);
#define wait(a) posix_wait(a)
/* #ifdef wrapped functions that need defining for clean compiling */
pid_t getppid(void);
void vhangup(void);
int innetgr(const char *, const char *, const char *, const char *);
/* TERMCAP */
int tcgetattr(int, struct termios *);
int tcsetattr(int, int, const struct termios *);
int tcsetpgrp(int, pid_t);
speed_t cfgetospeed(const struct termios *);
speed_t cfgetispeed(const struct termios *);
int cfsetospeed(struct termios *, int);
int cfsetispeed(struct termios *, int);
#endif /* HAVE_NEXT */
#endif /* _NEXT_POSIX_H */

View File

@ -0,0 +1,220 @@
/*
* Please note: this implementation of openpty() is far from complete.
* it is just enough for portable OpenSSH's needs.
*/
/*
* Copyright (c) 2004 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Allocating a pseudo-terminal, and making it the controlling tty.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
#if !defined(HAVE_OPENPTY)
#include <sys/types.h>
#include <stdlib.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_UTIL_H
# include <util.h>
#endif /* HAVE_UTIL_H */
#ifdef HAVE_PTY_H
# include <pty.h>
#endif
#if defined(HAVE_DEV_PTMX) && defined(HAVE_SYS_STROPTS_H)
# include <sys/stropts.h>
#endif
#include <signal.h>
#include <string.h>
#include <unistd.h>
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
int
openpty(int *amaster, int *aslave, char *name, struct termios *termp,
struct winsize *winp)
{
#if defined(HAVE__GETPTY)
/*
* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
* pty's automagically when needed
*/
char *slave;
if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL)
return (-1);
/* Open the slave side. */
if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) {
close(*amaster);
return (-1);
}
return (0);
#elif defined(HAVE_DEV_PTMX)
/*
* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3
* also has bsd-style ptys, but they simply do not work.)
*/
int ptm;
char *pts;
mysig_t old_signal;
if ((ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1)
return (-1);
/* XXX: need to close ptm on error? */
old_signal = signal(SIGCHLD, SIG_DFL);
if (grantpt(ptm) < 0)
return (-1);
signal(SIGCHLD, old_signal);
if (unlockpt(ptm) < 0)
return (-1);
if ((pts = ptsname(ptm)) == NULL)
return (-1);
*amaster = ptm;
/* Open the slave side. */
if ((*aslave = open(pts, O_RDWR | O_NOCTTY)) == -1) {
close(*amaster);
return (-1);
}
/*
* Try to push the appropriate streams modules, as described
* in Solaris pts(7).
*/
ioctl(*aslave, I_PUSH, "ptem");
ioctl(*aslave, I_PUSH, "ldterm");
# ifndef __hpux
ioctl(*aslave, I_PUSH, "ttcompat");
# endif /* __hpux */
return (0);
#elif defined(HAVE_DEV_PTS_AND_PTC)
/* AIX-style pty code. */
const char *ttname;
if ((*amaster = open("/dev/ptc", O_RDWR | O_NOCTTY)) == -1)
return (-1);
if ((ttname = ttyname(*amaster)) == NULL)
return (-1);
if ((*aslave = open(ttname, O_RDWR | O_NOCTTY)) == -1) {
close(*amaster);
return (-1);
}
return (0);
#elif defined(_UNICOS)
char ptbuf[64], ttbuf[64];
int i;
int highpty;
highpty = 128;
#ifdef _SC_CRAY_NPTY
if ((highpty = sysconf(_SC_CRAY_NPTY)) == -1)
highpty = 128;
#endif /* _SC_CRAY_NPTY */
for (i = 0; i < highpty; i++) {
snprintf(ptbuf, sizeof(ptbuf), "/dev/pty/%03d", i);
snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%03d", i);
if ((*amaster = open(ptbuf, O_RDWR|O_NOCTTY)) == -1)
continue;
/* Open the slave side. */
if ((*aslave = open(ttbuf, O_RDWR|O_NOCTTY)) == -1) {
close(*amaster);
return (-1);
}
return (0);
}
return (-1);
#else
/* BSD-style pty code. */
char ptbuf[64], ttbuf[64];
int i;
const char *ptymajors = "pqrstuvwxyzabcdefghijklmno"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char *ptyminors = "0123456789abcdef";
int num_minors = strlen(ptyminors);
int num_ptys = strlen(ptymajors) * num_minors;
struct termios tio;
for (i = 0; i < num_ptys; i++) {
snprintf(ptbuf, sizeof(ptbuf), "/dev/pty%c%c",
ptymajors[i / num_minors], ptyminors[i % num_minors]);
snprintf(ttbuf, sizeof(ttbuf), "/dev/tty%c%c",
ptymajors[i / num_minors], ptyminors[i % num_minors]);
if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1) {
/* Try SCO style naming */
snprintf(ptbuf, sizeof(ptbuf), "/dev/ptyp%d", i);
snprintf(ttbuf, sizeof(ttbuf), "/dev/ttyp%d", i);
if ((*amaster = open(ptbuf, O_RDWR | O_NOCTTY)) == -1)
continue;
}
/* Open the slave side. */
if ((*aslave = open(ttbuf, O_RDWR | O_NOCTTY)) == -1) {
close(*amaster);
return (-1);
}
/* set tty modes to a sane state for broken clients */
if (tcgetattr(*amaster, &tio) != -1) {
tio.c_lflag |= (ECHO | ISIG | ICANON);
tio.c_oflag |= (OPOST | ONLCR);
tio.c_iflag |= ICRNL;
tcsetattr(*amaster, TCSANOW, &tio);
}
return (0);
}
return (-1);
#endif
}
#endif /* !defined(HAVE_OPENPTY) */

117
openbsd-compat/bsd-poll.c Normal file
View File

@ -0,0 +1,117 @@
/* $Id: bsd-poll.c,v 1.2 2008/02/29 02:57:47 dtucker Exp $ */
/*
* Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au).
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#if !defined(HAVE_POLL)
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#include <errno.h>
#include "bsd-poll.h"
/*
* A minimal implementation of poll(2), built on top of select(2).
*
* Only supports POLLIN and POLLOUT flags in pfd.events, and POLLIN, POLLOUT
* and POLLERR flags in revents.
*
* Supports pfd.fd = -1 meaning "unused" although it's not standard.
*/
int
poll(struct pollfd *fds, nfds_t nfds, int timeout)
{
nfds_t i;
int saved_errno, ret, fd, maxfd = 0;
fd_set *readfds = NULL, *writefds = NULL, *exceptfds = NULL;
size_t nmemb;
struct timeval tv, *tvp = NULL;
for (i = 0; i < nfds; i++) {
if (fd >= FD_SETSIZE) {
errno = EINVAL;
return -1;
}
maxfd = MAX(maxfd, fds[i].fd);
}
nmemb = howmany(maxfd + 1 , NFDBITS);
if ((readfds = calloc(nmemb, sizeof(fd_mask))) == NULL ||
(writefds = calloc(nmemb, sizeof(fd_mask))) == NULL ||
(exceptfds = calloc(nmemb, sizeof(fd_mask))) == NULL) {
saved_errno = ENOMEM;
ret = -1;
goto out;
}
/* populate event bit vectors for the events we're interested in */
for (i = 0; i < nfds; i++) {
fd = fds[i].fd;
if (fd == -1)
continue;
if (fds[i].events & POLLIN) {
FD_SET(fd, readfds);
FD_SET(fd, exceptfds);
}
if (fds[i].events & POLLOUT) {
FD_SET(fd, writefds);
FD_SET(fd, exceptfds);
}
}
/* poll timeout is msec, select is timeval (sec + usec) */
if (timeout >= 0) {
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
tvp = &tv;
}
ret = select(maxfd + 1, readfds, writefds, exceptfds, tvp);
saved_errno = errno;
/* scan through select results and set poll() flags */
for (i = 0; i < nfds; i++) {
fd = fds[i].fd;
fds[i].revents = 0;
if (fd == -1)
continue;
if (FD_ISSET(fd, readfds)) {
fds[i].revents |= POLLIN;
}
if (FD_ISSET(fd, writefds)) {
fds[i].revents |= POLLOUT;
}
if (FD_ISSET(fd, exceptfds)) {
fds[i].revents |= POLLERR;
}
}
out:
if (readfds != NULL)
free(readfds);
if (writefds != NULL)
free(writefds);
if (exceptfds != NULL)
free(exceptfds);
if (ret == -1)
errno = saved_errno;
return ret;
}
#endif

61
openbsd-compat/bsd-poll.h Normal file
View File

@ -0,0 +1,61 @@
/* $OpenBSD: poll.h,v 1.11 2003/12/10 23:10:08 millert Exp $ */
/*
* Copyright (c) 1996 Theo de Raadt
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
/* OPENBSD ORIGINAL: sys/sys/poll.h */
#if !defined(HAVE_POLL) && !defined(HAVE_POLL_H)
#ifndef _COMPAT_POLL_H_
#define _COMPAT_POLL_H_
typedef struct pollfd {
int fd;
short events;
short revents;
} pollfd_t;
typedef unsigned int nfds_t;
#define POLLIN 0x0001
#define POLLOUT 0x0004
#define POLLERR 0x0008
#if 0
/* the following are currently not implemented */
#define POLLPRI 0x0002
#define POLLHUP 0x0010
#define POLLNVAL 0x0020
#define POLLRDNORM 0x0040
#define POLLNORM POLLRDNORM
#define POLLWRNORM POLLOUT
#define POLLRDBAND 0x0080
#define POLLWRBAND 0x0100
#endif
#define INFTIM (-1) /* not standard */
int poll(struct pollfd *, nfds_t, int);
#endif /* !_COMPAT_POLL_H_ */
#endif /* !HAVE_POLL_H */

View File

@ -0,0 +1,850 @@
/*
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell (papowell@astart.com)
* It may be used for any purpose as long as this notice remains intact
* on all source code distributions
*/
/**************************************************************
* Original:
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
* A bombproof version of doprnt (dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that
* the version here does not include floating point...
*
* snprintf() is used instead of sprintf() as it does limit checks
* for string length. This covers a nasty loophole.
*
* The other functions are there to prevent NULL pointers from
* causing nast effects.
*
* More Recently:
* Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
* This was ugly. It is still ugly. I opted out of floating point
* numbers, but the formatter understands just about everything
* from the normal C string format, at least as far as I can tell from
* the Solaris 2.5 printf(3S) man page.
*
* Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
* Ok, added some minimal floating point support, which means this
* probably requires libm on most operating systems. Don't yet
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
* was pretty badly broken, it just wasn't being exercised in ways
* which showed it, so that's been fixed. Also, formated the code
* to mutt conventions, and removed dead code left over from the
* original. Also, there is now a builtin-test, just compile with:
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
* and run snprintf for results.
*
* Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
* The PGP code was using unsigned hexadecimal formats.
* Unfortunately, unsigned formats simply didn't work.
*
* Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
* The original code assumed that both snprintf() and vsnprintf() were
* missing. Some systems only have snprintf() but not vsnprintf(), so
* the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
*
* Andrew Tridgell (tridge@samba.org) Oct 1998
* fixed handling of %.0f
* added test for HAVE_LONG_DOUBLE
*
* tridge@samba.org, idra@samba.org, April 2001
* got rid of fcvt code (twas buggy and made testing harder)
* added C99 semantics
*
* date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0
* actually print args for %g and %e
*
* date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0
* Since includes.h isn't included here, VA_COPY has to be defined here. I don't
* see any include file that is guaranteed to be here, so I'm defining it
* locally. Fixes AIX and Solaris builds.
*
* date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13
* put the ifdef for HAVE_VA_COPY in one place rather than in lots of
* functions
*
* date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4
* Fix usage of va_list passed as an arg. Use __va_copy before using it
* when it exists.
*
* date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14
* Fix incorrect zpadlen handling in fmtfp.
* Thanks to Ollie Oldham <ollie.oldham@metro-optix.com> for spotting it.
* few mods to make it easier to compile the tests.
* addedd the "Ollie" test to the floating point ones.
*
* Martin Pool (mbp@samba.org) April 2003
* Remove NO_CONFIG_H so that the test case can be built within a source
* tree with less trouble.
* Remove unnecessary SAFE_FREE() definition.
*
* Martin Pool (mbp@samba.org) May 2003
* Put in a prototype for dummy_snprintf() to quiet compiler warnings.
*
* Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
* if the C library has some snprintf functions already.
*
* Damien Miller (djm@mindrot.org) Jan 2007
* Fix integer overflows in return value.
* Make formatting quite a bit faster by inlining dopr_outch()
*
**************************************************************/
#include "includes.h"
#if defined(BROKEN_SNPRINTF) /* For those with broken snprintf() */
# undef HAVE_SNPRINTF
# undef HAVE_VSNPRINTF
#endif
#ifndef VA_COPY
# ifdef HAVE_VA_COPY
# define VA_COPY(dest, src) va_copy(dest, src)
# else
# ifdef HAVE___VA_COPY
# define VA_COPY(dest, src) __va_copy(dest, src)
# else
# define VA_COPY(dest, src) (dest) = (src)
# endif
# endif
#endif
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#ifdef HAVE_LONG_DOUBLE
# define LDOUBLE long double
#else
# define LDOUBLE double
#endif
#ifdef HAVE_LONG_LONG
# define LLONG long long
#else
# define LLONG long
#endif
/*
* dopr(): poor man's version of doprintf
*/
/* format read states */
#define DP_S_DEFAULT 0
#define DP_S_FLAGS 1
#define DP_S_MIN 2
#define DP_S_DOT 3
#define DP_S_MAX 4
#define DP_S_MOD 5
#define DP_S_CONV 6
#define DP_S_DONE 7
/* format flags - Bits */
#define DP_F_MINUS (1 << 0)
#define DP_F_PLUS (1 << 1)
#define DP_F_SPACE (1 << 2)
#define DP_F_NUM (1 << 3)
#define DP_F_ZERO (1 << 4)
#define DP_F_UP (1 << 5)
#define DP_F_UNSIGNED (1 << 6)
/* Conversion Flags */
#define DP_C_SHORT 1
#define DP_C_LONG 2
#define DP_C_LDOUBLE 3
#define DP_C_LLONG 4
#define char_to_int(p) ((p)- '0')
#ifndef MAX
# define MAX(p,q) (((p) >= (q)) ? (p) : (q))
#endif
#define DOPR_OUTCH(buf, pos, buflen, thechar) \
do { \
if (pos + 1 >= INT_MAX) { \
errno = ERANGE; \
return -1; \
} \
if (pos < buflen) \
buf[pos] = thechar; \
(pos)++; \
} while (0)
static int dopr(char *buffer, size_t maxlen, const char *format,
va_list args_in);
static int fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
static int fmtint(char *buffer, size_t *currlen, size_t maxlen,
LLONG value, int base, int min, int max, int flags);
static int fmtfp(char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static int
dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
{
char ch;
LLONG value;
LDOUBLE fvalue;
char *strvalue;
int min;
int max;
int state;
int flags;
int cflags;
size_t currlen;
va_list args;
VA_COPY(args, args_in);
state = DP_S_DEFAULT;
currlen = flags = cflags = min = 0;
max = -1;
ch = *format++;
while (state != DP_S_DONE) {
if (ch == '\0')
state = DP_S_DONE;
switch(state) {
case DP_S_DEFAULT:
if (ch == '%')
state = DP_S_FLAGS;
else
DOPR_OUTCH(buffer, currlen, maxlen, ch);
ch = *format++;
break;
case DP_S_FLAGS:
switch (ch) {
case '-':
flags |= DP_F_MINUS;
ch = *format++;
break;
case '+':
flags |= DP_F_PLUS;
ch = *format++;
break;
case ' ':
flags |= DP_F_SPACE;
ch = *format++;
break;
case '#':
flags |= DP_F_NUM;
ch = *format++;
break;
case '0':
flags |= DP_F_ZERO;
ch = *format++;
break;
default:
state = DP_S_MIN;
break;
}
break;
case DP_S_MIN:
if (isdigit((unsigned char)ch)) {
min = 10*min + char_to_int (ch);
ch = *format++;
} else if (ch == '*') {
min = va_arg (args, int);
ch = *format++;
state = DP_S_DOT;
} else {
state = DP_S_DOT;
}
break;
case DP_S_DOT:
if (ch == '.') {
state = DP_S_MAX;
ch = *format++;
} else {
state = DP_S_MOD;
}
break;
case DP_S_MAX:
if (isdigit((unsigned char)ch)) {
if (max < 0)
max = 0;
max = 10*max + char_to_int (ch);
ch = *format++;
} else if (ch == '*') {
max = va_arg (args, int);
ch = *format++;
state = DP_S_MOD;
} else {
state = DP_S_MOD;
}
break;
case DP_S_MOD:
switch (ch) {
case 'h':
cflags = DP_C_SHORT;
ch = *format++;
break;
case 'l':
cflags = DP_C_LONG;
ch = *format++;
if (ch == 'l') { /* It's a long long */
cflags = DP_C_LLONG;
ch = *format++;
}
break;
case 'L':
cflags = DP_C_LDOUBLE;
ch = *format++;
break;
default:
break;
}
state = DP_S_CONV;
break;
case DP_S_CONV:
switch (ch) {
case 'd':
case 'i':
if (cflags == DP_C_SHORT)
value = va_arg (args, int);
else if (cflags == DP_C_LONG)
value = va_arg (args, long int);
else if (cflags == DP_C_LLONG)
value = va_arg (args, LLONG);
else
value = va_arg (args, int);
if (fmtint(buffer, &currlen, maxlen,
value, 10, min, max, flags) == -1)
return -1;
break;
case 'o':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (long)va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
if (fmtint(buffer, &currlen, maxlen, value,
8, min, max, flags) == -1)
return -1;
break;
case 'u':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (LLONG)va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
if (fmtint(buffer, &currlen, maxlen, value,
10, min, max, flags) == -1)
return -1;
break;
case 'X':
flags |= DP_F_UP;
case 'x':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else if (cflags == DP_C_LLONG)
value = (LLONG)va_arg (args, unsigned LLONG);
else
value = (long)va_arg (args, unsigned int);
if (fmtint(buffer, &currlen, maxlen, value,
16, min, max, flags) == -1)
return -1;
break;
case 'f':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
if (fmtfp(buffer, &currlen, maxlen, fvalue,
min, max, flags) == -1)
return -1;
break;
case 'E':
flags |= DP_F_UP;
case 'e':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
if (fmtfp(buffer, &currlen, maxlen, fvalue,
min, max, flags) == -1)
return -1;
break;
case 'G':
flags |= DP_F_UP;
case 'g':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
if (fmtfp(buffer, &currlen, maxlen, fvalue,
min, max, flags) == -1)
return -1;
break;
case 'c':
DOPR_OUTCH(buffer, currlen, maxlen,
va_arg (args, int));
break;
case 's':
strvalue = va_arg (args, char *);
if (!strvalue) strvalue = "(NULL)";
if (max == -1) {
max = strlen(strvalue);
}
if (min > 0 && max >= 0 && min > max) max = min;
if (fmtstr(buffer, &currlen, maxlen,
strvalue, flags, min, max) == -1)
return -1;
break;
case 'p':
strvalue = va_arg (args, void *);
if (fmtint(buffer, &currlen, maxlen,
(long) strvalue, 16, min, max, flags) == -1)
return -1;
break;
case 'n':
if (cflags == DP_C_SHORT) {
short int *num;
num = va_arg (args, short int *);
*num = currlen;
} else if (cflags == DP_C_LONG) {
long int *num;
num = va_arg (args, long int *);
*num = (long int)currlen;
} else if (cflags == DP_C_LLONG) {
LLONG *num;
num = va_arg (args, LLONG *);
*num = (LLONG)currlen;
} else {
int *num;
num = va_arg (args, int *);
*num = currlen;
}
break;
case '%':
DOPR_OUTCH(buffer, currlen, maxlen, ch);
break;
case 'w':
/* not supported yet, treat as next char */
ch = *format++;
break;
default:
/* Unknown, skip */
break;
}
ch = *format++;
state = DP_S_DEFAULT;
flags = cflags = min = 0;
max = -1;
break;
case DP_S_DONE:
break;
default:
/* hmm? */
break; /* some picky compilers need this */
}
}
if (maxlen != 0) {
if (currlen < maxlen - 1)
buffer[currlen] = '\0';
else if (maxlen > 0)
buffer[maxlen - 1] = '\0';
}
return currlen < INT_MAX ? (int)currlen : -1;
}
static int
fmtstr(char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max)
{
int padlen, strln; /* amount to pad */
int cnt = 0;
#ifdef DEBUG_SNPRINTF
printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
#endif
if (value == 0) {
value = "<NULL>";
}
for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */
padlen = min - strln;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justify */
while ((padlen > 0) && (cnt < max)) {
DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
--padlen;
++cnt;
}
while (*value && (cnt < max)) {
DOPR_OUTCH(buffer, *currlen, maxlen, *value);
*value++;
++cnt;
}
while ((padlen < 0) && (cnt < max)) {
DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
++padlen;
++cnt;
}
return 0;
}
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
static int
fmtint(char *buffer, size_t *currlen, size_t maxlen,
LLONG value, int base, int min, int max, int flags)
{
int signvalue = 0;
unsigned LLONG uvalue;
char convert[20];
int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
int caps = 0;
if (max < 0)
max = 0;
uvalue = value;
if(!(flags & DP_F_UNSIGNED)) {
if( value < 0 ) {
signvalue = '-';
uvalue = -value;
} else {
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
signvalue = '+';
else if (flags & DP_F_SPACE)
signvalue = ' ';
}
}
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
do {
convert[place++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")
[uvalue % (unsigned)base ];
uvalue = (uvalue / (unsigned)base );
} while(uvalue && (place < 20));
if (place == 20) place--;
convert[place] = 0;
zpadlen = max - place;
spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
if (zpadlen < 0) zpadlen = 0;
if (spadlen < 0) spadlen = 0;
if (flags & DP_F_ZERO) {
zpadlen = MAX(zpadlen, spadlen);
spadlen = 0;
}
if (flags & DP_F_MINUS)
spadlen = -spadlen; /* Left Justifty */
#ifdef DEBUG_SNPRINTF
printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
zpadlen, spadlen, min, max, place);
#endif
/* Spaces */
while (spadlen > 0) {
DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
--spadlen;
}
/* Sign */
if (signvalue)
DOPR_OUTCH(buffer, *currlen, maxlen, signvalue);
/* Zeros */
if (zpadlen > 0) {
while (zpadlen > 0) {
DOPR_OUTCH(buffer, *currlen, maxlen, '0');
--zpadlen;
}
}
/* Digits */
while (place > 0) {
--place;
DOPR_OUTCH(buffer, *currlen, maxlen, convert[place]);
}
/* Left Justified spaces */
while (spadlen < 0) {
DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
++spadlen;
}
return 0;
}
static LDOUBLE abs_val(LDOUBLE value)
{
LDOUBLE result = value;
if (value < 0)
result = -value;
return result;
}
static LDOUBLE POW10(int val)
{
LDOUBLE result = 1;
while (val) {
result *= 10;
val--;
}
return result;
}
static LLONG ROUND(LDOUBLE value)
{
LLONG intpart;
intpart = (LLONG)value;
value = value - intpart;
if (value >= 0.5) intpart++;
return intpart;
}
/* a replacement for modf that doesn't need the math library. Should
be portable, but slow */
static double my_modf(double x0, double *iptr)
{
int i;
long l;
double x = x0;
double f = 1.0;
for (i=0;i<100;i++) {
l = (long)x;
if (l <= (x+1) && l >= (x-1)) break;
x *= 0.1;
f *= 10.0;
}
if (i == 100) {
/*
* yikes! the number is beyond what we can handle.
* What do we do?
*/
(*iptr) = 0;
return 0;
}
if (i != 0) {
double i2;
double ret;
ret = my_modf(x0-l*f, &i2);
(*iptr) = l*f + i2;
return ret;
}
(*iptr) = l;
return x - (*iptr);
}
static int
fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags)
{
int signvalue = 0;
double ufvalue;
char iconvert[311];
char fconvert[311];
int iplace = 0;
int fplace = 0;
int padlen = 0; /* amount to pad */
int zpadlen = 0;
int caps = 0;
int idx;
double intpart;
double fracpart;
double temp;
/*
* AIX manpage says the default is 0, but Solaris says the default
* is 6, and sprintf on AIX defaults to 6
*/
if (max < 0)
max = 6;
ufvalue = abs_val (fvalue);
if (fvalue < 0) {
signvalue = '-';
} else {
if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
signvalue = '+';
} else {
if (flags & DP_F_SPACE)
signvalue = ' ';
}
}
#if 0
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
#endif
#if 0
if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
#endif
/*
* Sorry, we only support 16 digits past the decimal because of our
* conversion method
*/
if (max > 16)
max = 16;
/* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of 10
*/
temp = ufvalue;
my_modf(temp, &intpart);
fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
if (fracpart >= POW10(max)) {
intpart++;
fracpart -= POW10(max);
}
/* Convert integer part */
do {
temp = intpart*0.1;
my_modf(temp, &intpart);
idx = (int) ((temp -intpart +0.05)* 10.0);
/* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
/* printf ("%llf, %f, %x\n", temp, intpart, idx); */
iconvert[iplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
} while (intpart && (iplace < 311));
if (iplace == 311) iplace--;
iconvert[iplace] = 0;
/* Convert fractional part */
if (fracpart)
{
do {
temp = fracpart*0.1;
my_modf(temp, &fracpart);
idx = (int) ((temp -fracpart +0.05)* 10.0);
/* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
/* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
fconvert[fplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
} while(fracpart && (fplace < 311));
if (fplace == 311) fplace--;
}
fconvert[fplace] = 0;
/* -1 for decimal point, another -1 if we are printing a sign */
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
zpadlen = max - fplace;
if (zpadlen < 0) zpadlen = 0;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justifty */
if ((flags & DP_F_ZERO) && (padlen > 0)) {
if (signvalue) {
DOPR_OUTCH(buffer, *currlen, maxlen, signvalue);
--padlen;
signvalue = 0;
}
while (padlen > 0) {
DOPR_OUTCH(buffer, *currlen, maxlen, '0');
--padlen;
}
}
while (padlen > 0) {
DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
--padlen;
}
if (signvalue)
DOPR_OUTCH(buffer, *currlen, maxlen, signvalue);
while (iplace > 0) {
--iplace;
DOPR_OUTCH(buffer, *currlen, maxlen, iconvert[iplace]);
}
#ifdef DEBUG_SNPRINTF
printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
#endif
/*
* Decimal point. This should probably use locale to find the correct
* char to print out.
*/
if (max > 0) {
DOPR_OUTCH(buffer, *currlen, maxlen, '.');
while (zpadlen > 0) {
DOPR_OUTCH(buffer, *currlen, maxlen, '0');
--zpadlen;
}
while (fplace > 0) {
--fplace;
DOPR_OUTCH(buffer, *currlen, maxlen, fconvert[fplace]);
}
}
while (padlen < 0) {
DOPR_OUTCH(buffer, *currlen, maxlen, ' ');
++padlen;
}
return 0;
}
#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
#if !defined(HAVE_VSNPRINTF)
int
vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
return dopr(str, count, fmt, args);
}
#endif
#if !defined(HAVE_SNPRINTF)
int
snprintf(char *str, size_t count, SNPRINTF_CONST char *fmt, ...)
{
size_t ret;
va_list ap;
va_start(ap, fmt);
ret = vsnprintf(str, count, fmt, ap);
va_end(ap);
return ret;
}
#endif

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2000 Ben Lindstrom. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "includes.h"
#ifndef HAVE_WAITPID
#include <errno.h>
#include <sys/wait.h>
#include "bsd-waitpid.h"
pid_t
waitpid(int pid, int *stat_loc, int options)
{
union wait statusp;
pid_t wait_pid;
if (pid <= 0) {
if (pid != -1) {
errno = EINVAL;
return (-1);
}
/* wait4() wants pid=0 for indiscriminate wait. */
pid = 0;
}
wait_pid = wait4(pid, &statusp, options, NULL);
if (stat_loc)
*stat_loc = (int) statusp.w_status;
return (wait_pid);
}
#endif /* !HAVE_WAITPID */

View File

@ -0,0 +1,51 @@
/* $Id: bsd-waitpid.h,v 1.5 2003/08/29 16:59:52 mouring Exp $ */
/*
* Copyright (c) 2000 Ben Lindstrom. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _BSD_WAITPID_H
#define _BSD_WAITPID_H
#ifndef HAVE_WAITPID
/* Clean out any potental issues */
#undef WIFEXITED
#undef WIFSTOPPED
#undef WIFSIGNALED
/* Define required functions to mimic a POSIX look and feel */
#define _W_INT(w) (*(int*)&(w)) /* convert union wait to int */
#define WIFEXITED(w) (!((_W_INT(w)) & 0377))
#define WIFSTOPPED(w) ((_W_INT(w)) & 0100)
#define WIFSIGNALED(w) (!WIFEXITED(w) && !WIFSTOPPED(w))
#define WEXITSTATUS(w) (int)(WIFEXITED(w) ? ((_W_INT(w) >> 8) & 0377) : -1)
#define WTERMSIG(w) (int)(WIFSIGNALED(w) ? (_W_INT(w) & 0177) : -1)
#define WCOREFLAG 0x80
#define WCOREDUMP(w) ((_W_INT(w)) & WCOREFLAG)
/* Prototype */
pid_t waitpid(int, int *, int);
#endif /* !HAVE_WAITPID */
#endif /* _BSD_WAITPID_H */

92
openbsd-compat/daemon.c Normal file
View File

@ -0,0 +1,92 @@
/* $OpenBSD: daemon.c,v 1.6 2005/08/08 08:05:33 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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.
*/
/* OPENBSD ORIGINAL: lib/libc/gen/daemon.c */
#include "includes.h"
#ifndef HAVE_DAEMON
#include <sys/types.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
int
daemon(int nochdir, int noclose)
{
int fd;
switch (fork()) {
case -1:
return (-1);
case 0:
#ifdef HAVE_CYGWIN
register_9x_service();
#endif
break;
default:
#ifdef HAVE_CYGWIN
/*
* This sleep avoids a race condition which kills the
* child process if parent is started by a NT/W2K service.
*/
sleep(1);
#endif
_exit(0);
}
if (setsid() == -1)
return (-1);
if (!nochdir)
(void)chdir("/");
if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
(void)dup2(fd, STDIN_FILENO);
(void)dup2(fd, STDOUT_FILENO);
(void)dup2(fd, STDERR_FILENO);
if (fd > 2)
(void)close (fd);
}
return (0);
}
#endif /* !HAVE_DAEMON */

72
openbsd-compat/dirname.c Normal file
View File

@ -0,0 +1,72 @@
/* $OpenBSD: dirname.c,v 1.13 2005/08/08 08:05:33 espie Exp $ */
/*
* Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* OPENBSD ORIGINAL: lib/libc/gen/dirname.c */
#include "includes.h"
#ifndef HAVE_DIRNAME
#include <errno.h>
#include <string.h>
#include <sys/param.h>
char *
dirname(const char *path)
{
static char dname[MAXPATHLEN];
size_t len;
const char *endp;
/* Empty or NULL string gets treated as "." */
if (path == NULL || *path == '\0') {
dname[0] = '.';
dname[1] = '\0';
return (dname);
}
/* Strip any trailing slashes */
endp = path + strlen(path) - 1;
while (endp > path && *endp == '/')
endp--;
/* Find the start of the dir */
while (endp > path && *endp != '/')
endp--;
/* Either the dir is "/" or there are no slashes */
if (endp == path) {
dname[0] = *endp == '/' ? '/' : '.';
dname[1] = '\0';
return (dname);
} else {
/* Move forward past the separating slashes */
do {
endp--;
} while (endp > path && *endp == '/');
}
len = endp - path + 1;
if (len >= sizeof(dname)) {
errno = ENAMETOOLONG;
return (NULL);
}
memcpy(dname, path, len);
dname[len] = '\0';
return (dname);
}
#endif

View File

@ -0,0 +1,228 @@
/*
* Copyright (C) 2000-2003 Damien Miller. All rights reserved.
* Copyright (C) 1999 WIDE Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*/
/*
* Pseudo-implementation of RFC2553 name / address resolution functions
*
* But these functions are not implemented correctly. The minimum subset
* is implemented for ssh use only. For example, this routine assumes
* that ai_family is AF_INET. Don't use it for another purpose.
*/
#include "includes.h"
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifndef HAVE_GETNAMEINFO
int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
size_t hostlen, char *serv, size_t servlen, int flags)
{
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
struct hostent *hp;
char tmpserv[16];
if (serv != NULL) {
snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
if (pamsshagentauth_strlcpy(serv, tmpserv, servlen) >= servlen)
return (EAI_MEMORY);
}
if (host != NULL) {
if (flags & NI_NUMERICHOST) {
if (pamsshagentauth_strlcpy(host, inet_ntoa(sin->sin_addr),
hostlen) >= hostlen)
return (EAI_MEMORY);
else
return (0);
} else {
hp = gethostbyaddr((char *)&sin->sin_addr,
sizeof(struct in_addr), AF_INET);
if (hp == NULL)
return (EAI_NODATA);
if (pamsshagentauth_strlcpy(host, hp->h_name, hostlen) >= hostlen)
return (EAI_MEMORY);
else
return (0);
}
}
return (0);
}
#endif /* !HAVE_GETNAMEINFO */
#ifndef HAVE_GAI_STRERROR
#ifdef HAVE_CONST_GAI_STRERROR_PROTO
const char *
#else
char *
#endif
gai_strerror(int err)
{
switch (err) {
case EAI_NODATA:
return ("no address associated with name");
case EAI_MEMORY:
return ("memory allocation failure.");
case EAI_NONAME:
return ("nodename nor servname provided, or not known");
default:
return ("unknown/invalid error.");
}
}
#endif /* !HAVE_GAI_STRERROR */
#ifndef HAVE_FREEADDRINFO
void
freeaddrinfo(struct addrinfo *ai)
{
struct addrinfo *next;
for(; ai != NULL;) {
next = ai->ai_next;
free(ai);
ai = next;
}
}
#endif /* !HAVE_FREEADDRINFO */
#ifndef HAVE_GETADDRINFO
static struct
addrinfo *malloc_ai(int port, u_long addr, const struct addrinfo *hints)
{
struct addrinfo *ai;
ai = malloc(sizeof(*ai) + sizeof(struct sockaddr_in));
if (ai == NULL)
return (NULL);
memset(ai, '\0', sizeof(*ai) + sizeof(struct sockaddr_in));
ai->ai_addr = (struct sockaddr *)(ai + 1);
/* XXX -- ssh doesn't use sa_len */
ai->ai_addrlen = sizeof(struct sockaddr_in);
ai->ai_addr->sa_family = ai->ai_family = AF_INET;
((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
/* XXX: the following is not generally correct, but does what we want */
if (hints->ai_socktype)
ai->ai_socktype = hints->ai_socktype;
else
ai->ai_socktype = SOCK_STREAM;
if (hints->ai_protocol)
ai->ai_protocol = hints->ai_protocol;
return (ai);
}
int
getaddrinfo(const char *hostname, const char *servname,
const struct addrinfo *hints, struct addrinfo **res)
{
struct hostent *hp;
struct servent *sp;
struct in_addr in;
int i;
long int port;
u_long addr;
port = 0;
if (servname != NULL) {
char *cp;
port = strtol(servname, &cp, 10);
if (port > 0 && port <= 65535 && *cp == '\0')
port = htons(port);
else if ((sp = getservbyname(servname, NULL)) != NULL)
port = sp->s_port;
else
port = 0;
}
if (hints && hints->ai_flags & AI_PASSIVE) {
addr = htonl(0x00000000);
if (hostname && inet_aton(hostname, &in) != 0)
addr = in.s_addr;
*res = malloc_ai(port, addr, hints);
if (*res == NULL)
return (EAI_MEMORY);
return (0);
}
if (!hostname) {
*res = malloc_ai(port, htonl(0x7f000001), hints);
if (*res == NULL)
return (EAI_MEMORY);
return (0);
}
if (inet_aton(hostname, &in)) {
*res = malloc_ai(port, in.s_addr, hints);
if (*res == NULL)
return (EAI_MEMORY);
return (0);
}
/* Don't try DNS if AI_NUMERICHOST is set */
if (hints && hints->ai_flags & AI_NUMERICHOST)
return (EAI_NONAME);
hp = gethostbyname(hostname);
if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
struct addrinfo *cur, *prev;
cur = prev = *res = NULL;
for (i = 0; hp->h_addr_list[i]; i++) {
struct in_addr *in = (struct in_addr *)hp->h_addr_list[i];
cur = malloc_ai(port, in->s_addr, hints);
if (cur == NULL) {
if (*res != NULL)
freeaddrinfo(*res);
return (EAI_MEMORY);
}
if (prev)
prev->ai_next = cur;
else
*res = cur;
prev = cur;
}
return (0);
}
return (EAI_NODATA);
}
#endif /* !HAVE_GETADDRINFO */

View File

@ -0,0 +1,171 @@
/* $Id: fake-rfc2553.h,v 1.14 2008/02/25 09:21:20 dtucker Exp $ */
/*
* Copyright (C) 2000-2003 Damien Miller. All rights reserved.
* Copyright (C) 1999 WIDE Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*/
/*
* Pseudo-implementation of RFC2553 name / address resolution functions
*
* But these functions are not implemented correctly. The minimum subset
* is implemented for ssh use only. For example, this routine assumes
* that ai_family is AF_INET. Don't use it for another purpose.
*/
#ifndef _FAKE_RFC2553_H
#define _FAKE_RFC2553_H
#include "includes.h"
#include <sys/types.h>
#if defined(HAVE_NETDB_H)
# include <netdb.h>
#endif
/*
* First, socket and INET6 related definitions
*/
#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
# define _SS_MAXSIZE 128 /* Implementation specific max size */
# define _SS_PADSIZE (_SS_MAXSIZE - sizeof (struct sockaddr))
struct sockaddr_storage {
struct sockaddr ss_sa;
char __ss_pad2[_SS_PADSIZE];
};
# define ss_family ss_sa.sa_family
#endif /* !HAVE_STRUCT_SOCKADDR_STORAGE */
#ifndef IN6_IS_ADDR_LOOPBACK
# define IN6_IS_ADDR_LOOPBACK(a) \
(((u_int32_t *)(a))[0] == 0 && ((u_int32_t *)(a))[1] == 0 && \
((u_int32_t *)(a))[2] == 0 && ((u_int32_t *)(a))[3] == htonl(1))
#endif /* !IN6_IS_ADDR_LOOPBACK */
#ifndef HAVE_STRUCT_IN6_ADDR
struct in6_addr {
u_int8_t s6_addr[16];
};
#endif /* !HAVE_STRUCT_IN6_ADDR */
#ifndef HAVE_STRUCT_SOCKADDR_IN6
struct sockaddr_in6 {
unsigned short sin6_family;
u_int16_t sin6_port;
u_int32_t sin6_flowinfo;
struct in6_addr sin6_addr;
};
#endif /* !HAVE_STRUCT_SOCKADDR_IN6 */
#ifndef AF_INET6
/* Define it to something that should never appear */
#define AF_INET6 AF_MAX
#endif
/*
* Next, RFC2553 name / address resolution API
*/
#ifndef NI_NUMERICHOST
# define NI_NUMERICHOST (1)
#endif
#ifndef NI_NAMEREQD
# define NI_NAMEREQD (1<<1)
#endif
#ifndef NI_NUMERICSERV
# define NI_NUMERICSERV (1<<2)
#endif
#ifndef AI_PASSIVE
# define AI_PASSIVE (1)
#endif
#ifndef AI_CANONNAME
# define AI_CANONNAME (1<<1)
#endif
#ifndef AI_NUMERICHOST
# define AI_NUMERICHOST (1<<2)
#endif
#ifndef NI_MAXSERV
# define NI_MAXSERV 32
#endif /* !NI_MAXSERV */
#ifndef NI_MAXHOST
# define NI_MAXHOST 1025
#endif /* !NI_MAXHOST */
#ifndef EAI_NODATA
# define EAI_NODATA (INT_MAX - 1)
#endif
#ifndef EAI_MEMORY
# define EAI_MEMORY (INT_MAX - 2)
#endif
#ifndef EAI_NONAME
# define EAI_NONAME (INT_MAX - 3)
#endif
#ifndef EAI_SYSTEM
# define EAI_SYSTEM (INT_MAX - 4)
#endif
#ifndef HAVE_STRUCT_ADDRINFO
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
size_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for hostname */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
};
#endif /* !HAVE_STRUCT_ADDRINFO */
#ifndef HAVE_GETADDRINFO
#ifdef getaddrinfo
# undef getaddrinfo
#endif
#define getaddrinfo(a,b,c,d) (ssh_getaddrinfo(a,b,c,d))
int getaddrinfo(const char *, const char *,
const struct addrinfo *, struct addrinfo **);
#endif /* !HAVE_GETADDRINFO */
#if !defined(HAVE_GAI_STRERROR) && !defined(HAVE_CONST_GAI_STRERROR_PROTO)
#define gai_strerror(a) (_ssh_compat_gai_strerror(a))
char *gai_strerror(int);
#endif /* !HAVE_GAI_STRERROR */
#ifndef HAVE_FREEADDRINFO
#define freeaddrinfo(a) (ssh_freeaddrinfo(a))
void freeaddrinfo(struct addrinfo *);
#endif /* !HAVE_FREEADDRINFO */
#ifndef HAVE_GETNAMEINFO
#define getnameinfo(a,b,c,d,e,f,g) (ssh_getnameinfo(a,b,c,d,e,f,g))
int getnameinfo(const struct sockaddr *, size_t, char *, size_t,
char *, size_t, int);
#endif /* !HAVE_GETNAMEINFO */
#endif /* !_FAKE_RFC2553_H */

240
openbsd-compat/getcwd.c Normal file
View File

@ -0,0 +1,240 @@
/* $OpenBSD: getcwd.c,v 1.14 2005/08/08 08:05:34 espie Exp $ */
/*
* Copyright (c) 1989, 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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.
*/
/* OPENBSD ORIGINAL: lib/libc/gen/getcwd.c */
#include "includes.h"
#if !defined(HAVE_GETCWD)
#include <sys/param.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>
#include <sys/dir.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "includes.h"
#define ISDOT(dp) \
(dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
(dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
char *
getcwd(char *pt, size_t size)
{
struct dirent *dp;
DIR *dir = NULL;
dev_t dev;
ino_t ino;
int first;
char *bpt, *bup;
struct stat s;
dev_t root_dev;
ino_t root_ino;
size_t ptsize, upsize;
int save_errno;
char *ept, *eup, *up;
/*
* If no buffer specified by the user, allocate one as necessary.
* If a buffer is specified, the size has to be non-zero. The path
* is built from the end of the buffer backwards.
*/
if (pt) {
ptsize = 0;
if (!size) {
errno = EINVAL;
return (NULL);
}
ept = pt + size;
} else {
if ((pt = malloc(ptsize = MAXPATHLEN)) == NULL)
return (NULL);
ept = pt + ptsize;
}
bpt = ept - 1;
*bpt = '\0';
/*
* Allocate bytes for the string of "../"'s.
* Should always be enough (it's 340 levels). If it's not, allocate
* as necessary. Special * case the first stat, it's ".", not "..".
*/
if ((up = malloc(upsize = MAXPATHLEN)) == NULL)
goto err;
eup = up + upsize;
bup = up;
up[0] = '.';
up[1] = '\0';
/* Save root values, so know when to stop. */
if (stat("/", &s))
goto err;
root_dev = s.st_dev;
root_ino = s.st_ino;
errno = 0; /* XXX readdir has no error return. */
for (first = 1;; first = 0) {
/* Stat the current level. */
if (lstat(up, &s))
goto err;
/* Save current node values. */
ino = s.st_ino;
dev = s.st_dev;
/* Check for reaching root. */
if (root_dev == dev && root_ino == ino) {
*--bpt = '/';
/*
* It's unclear that it's a requirement to copy the
* path to the beginning of the buffer, but it's always
* been that way and stuff would probably break.
*/
memmove(pt, bpt, ept - bpt);
free(up);
return (pt);
}
/*
* Build pointer to the parent directory, allocating memory
* as necessary. Max length is 3 for "../", the largest
* possible component name, plus a trailing NUL.
*/
if (bup + 3 + MAXNAMLEN + 1 >= eup) {
char *nup;
if ((nup = realloc(up, upsize *= 2)) == NULL)
goto err;
bup = nup + (bup - up);
up = nup;
eup = up + upsize;
}
*bup++ = '.';
*bup++ = '.';
*bup = '\0';
/* Open and stat parent directory. */
if (!(dir = opendir(up)) || fstat(dirfd(dir), &s))
goto err;
/* Add trailing slash for next directory. */
*bup++ = '/';
/*
* If it's a mount point, have to stat each element because
* the inode number in the directory is for the entry in the
* parent directory, not the inode number of the mounted file.
*/
save_errno = 0;
if (s.st_dev == dev) {
for (;;) {
if (!(dp = readdir(dir)))
goto notfound;
if (dp->d_fileno == ino)
break;
}
} else
for (;;) {
if (!(dp = readdir(dir)))
goto notfound;
if (ISDOT(dp))
continue;
memcpy(bup, dp->d_name, dp->d_namlen + 1);
/* Save the first error for later. */
if (lstat(up, &s)) {
if (!save_errno)
save_errno = errno;
errno = 0;
continue;
}
if (s.st_dev == dev && s.st_ino == ino)
break;
}
/*
* Check for length of the current name, preceding slash,
* leading slash.
*/
if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
size_t len;
char *npt;
if (!ptsize) {
errno = ERANGE;
goto err;
}
len = ept - bpt;
if ((npt = realloc(pt, ptsize *= 2)) == NULL)
goto err;
bpt = npt + (bpt - pt);
pt = npt;
ept = pt + ptsize;
memmove(ept - len, bpt, len);
bpt = ept - len;
}
if (!first)
*--bpt = '/';
bpt -= dp->d_namlen;
memcpy(bpt, dp->d_name, dp->d_namlen);
(void)closedir(dir);
/* Truncate any file name. */
*bup = '\0';
}
notfound:
/*
* If readdir set errno, use it, not any saved error; otherwise,
* didn't find the current directory in its parent directory, set
* errno to ENOENT.
*/
if (!errno)
errno = save_errno ? save_errno : ENOENT;
/* FALLTHROUGH */
err:
save_errno = errno;
if (ptsize)
free(pt);
free(up);
if (dir)
(void)closedir(dir);
errno = save_errno;
return (NULL);
}
#endif /* !defined(HAVE_GETCWD) */

View File

@ -0,0 +1,95 @@
/* $OpenBSD: getgrouplist.c,v 1.12 2005/08/08 08:05:34 espie Exp $ */
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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.
*/
/* OPENBSD ORIGINAL: lib/libc/gen/getgrouplist.c */
#include "includes.h"
#ifndef HAVE_GETGROUPLIST
/*
* get credential
*/
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <grp.h>
int
getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt)
{
struct group *grp;
int i, ngroups;
int ret, maxgroups;
int bail;
ret = 0;
ngroups = 0;
maxgroups = *grpcnt;
/*
* install primary group
*/
if (ngroups >= maxgroups) {
*grpcnt = ngroups;
return (-1);
}
groups[ngroups++] = agroup;
/*
* Scan the group file to find additional groups.
*/
setgrent();
while ((grp = getgrent())) {
if (grp->gr_gid == agroup)
continue;
for (bail = 0, i = 0; bail == 0 && i < ngroups; i++)
if (groups[i] == grp->gr_gid)
bail = 1;
if (bail)
continue;
for (i = 0; grp->gr_mem[i]; i++) {
if (!strcmp(grp->gr_mem[i], uname)) {
if (ngroups >= maxgroups) {
ret = -1;
goto out;
}
groups[ngroups++] = grp->gr_gid;
break;
}
}
}
out:
endgrent();
*grpcnt = ngroups;
return (ret);
}
#endif /* HAVE_GETGROUPLIST */

123
openbsd-compat/getopt.c Normal file
View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 1987, 1993, 1994
* 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. 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.
*/
/* OPENBSD ORIGINAL: lib/libc/stdlib/getopt.c */
#include "includes.h"
#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET)
#if defined(LIBC_SCCS) && !defined(lint)
static char *rcsid = "$OpenBSD: getopt.c,v 1.5 2003/06/02 20:18:37 millert Exp $";
#endif /* LIBC_SCCS and not lint */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int BSDopterr = 1, /* if error message should be printed */
BSDoptind = 1, /* index into parent argv vector */
BSDoptopt, /* character checked for validity */
BSDoptreset; /* reset getopt */
char *BSDoptarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
BSDgetopt(nargc, nargv, ostr)
int nargc;
char * const *nargv;
const char *ostr;
{
extern char *__progname;
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
if (ostr == NULL)
return (-1);
if (BSDoptreset || !*place) { /* update scanning pointer */
BSDoptreset = 0;
if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') {
place = EMSG;
return (-1);
}
if (place[1] && *++place == '-') { /* found "--" */
++BSDoptind;
place = EMSG;
return (-1);
}
} /* option letter okay? */
if ((BSDoptopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, BSDoptopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (BSDoptopt == (int)'-')
return (-1);
if (!*place)
++BSDoptind;
if (BSDopterr && *ostr != ':')
(void)fprintf(stderr,
"%s: illegal option -- %c\n", __progname, BSDoptopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
BSDoptarg = NULL;
if (!*place)
++BSDoptind;
}
else { /* need an argument */
if (*place) /* no white space */
BSDoptarg = place;
else if (nargc <= ++BSDoptind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (BSDopterr)
(void)fprintf(stderr,
"%s: option requires an argument -- %c\n",
__progname, BSDoptopt);
return (BADCH);
}
else /* white space */
BSDoptarg = nargv[BSDoptind];
place = EMSG;
++BSDoptind;
}
return (BSDoptopt); /* dump back option letter */
}
#endif /* !defined(HAVE_GETOPT) || !defined(HAVE_OPTRESET) */

View File

@ -0,0 +1,610 @@
/* $OpenBSD: getrrsetbyname.c,v 1.11 2007/10/11 18:36:41 jakob Exp $ */
/*
* Copyright (c) 2001 Jakob Schlyter. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
/*
* Portions Copyright (c) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* OPENBSD ORIGINAL: lib/libc/net/getrrsetbyname.c */
#include "includes.h"
#ifndef HAVE_GETRRSETBYNAME
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "getrrsetbyname.h"
#if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO
extern int h_errno;
#endif
/* We don't need multithread support here */
#ifdef _THREAD_PRIVATE
# undef _THREAD_PRIVATE
#endif
#define _THREAD_PRIVATE(a,b,c) (c)
#ifndef HAVE__RES_EXTERN
struct __res_state _res;
#endif
/* Necessary functions and macros */
/*
* Inline versions of get/put short/long. Pointer is advanced.
*
* These macros demonstrate the property of C whereby it can be
* portable or it can be elegant but rarely both.
*/
#ifndef INT32SZ
# define INT32SZ 4
#endif
#ifndef INT16SZ
# define INT16SZ 2
#endif
#ifndef GETSHORT
#define GETSHORT(s, cp) { \
register u_char *t_cp = (u_char *)(cp); \
(s) = ((u_int16_t)t_cp[0] << 8) \
| ((u_int16_t)t_cp[1]) \
; \
(cp) += INT16SZ; \
}
#endif
#ifndef GETLONG
#define GETLONG(l, cp) { \
register u_char *t_cp = (u_char *)(cp); \
(l) = ((u_int32_t)t_cp[0] << 24) \
| ((u_int32_t)t_cp[1] << 16) \
| ((u_int32_t)t_cp[2] << 8) \
| ((u_int32_t)t_cp[3]) \
; \
(cp) += INT32SZ; \
}
#endif
/*
* Routines to insert/extract short/long's.
*/
#ifndef HAVE__GETSHORT
static u_int16_t
_getshort(msgp)
register const u_char *msgp;
{
register u_int16_t u;
GETSHORT(u, msgp);
return (u);
}
#elif defined(HAVE_DECL__GETSHORT) && (HAVE_DECL__GETSHORT == 0)
u_int16_t _getshort(register const u_char *);
#endif
#ifndef HAVE__GETLONG
static u_int32_t
_getlong(msgp)
register const u_char *msgp;
{
register u_int32_t u;
GETLONG(u, msgp);
return (u);
}
#elif defined(HAVE_DECL__GETLONG) && (HAVE_DECL__GETLONG == 0)
u_int32_t _getlong(register const u_char *);
#endif
/* ************** */
#define ANSWER_BUFFER_SIZE 1024*64
struct dns_query {
char *name;
u_int16_t type;
u_int16_t class;
struct dns_query *next;
};
struct dns_rr {
char *name;
u_int16_t type;
u_int16_t class;
u_int16_t ttl;
u_int16_t size;
void *rdata;
struct dns_rr *next;
};
struct dns_response {
HEADER header;
struct dns_query *query;
struct dns_rr *answer;
struct dns_rr *authority;
struct dns_rr *additional;
};
static struct dns_response *parse_dns_response(const u_char *, int);
static struct dns_query *parse_dns_qsection(const u_char *, int,
const u_char **, int);
static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **,
int);
static void free_dns_query(struct dns_query *);
static void free_dns_rr(struct dns_rr *);
static void free_dns_response(struct dns_response *);
static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t);
int
getrrsetbyname(const char *hostname, unsigned int rdclass,
unsigned int rdtype, unsigned int flags,
struct rrsetinfo **res)
{
struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
int result;
struct rrsetinfo *rrset = NULL;
struct dns_response *response = NULL;
struct dns_rr *rr;
struct rdatainfo *rdata;
int length;
unsigned int index_ans, index_sig;
u_char answer[ANSWER_BUFFER_SIZE];
/* check for invalid class and type */
if (rdclass > 0xffff || rdtype > 0xffff) {
result = ERRSET_INVAL;
goto fail;
}
/* don't allow queries of class or type ANY */
if (rdclass == 0xff || rdtype == 0xff) {
result = ERRSET_INVAL;
goto fail;
}
/* don't allow flags yet, unimplemented */
if (flags) {
result = ERRSET_INVAL;
goto fail;
}
/* initialize resolver */
if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
result = ERRSET_FAIL;
goto fail;
}
#ifdef DEBUG
_resp->options |= RES_DEBUG;
#endif /* DEBUG */
#ifdef RES_USE_DNSSEC
/* turn on DNSSEC if EDNS0 is configured */
if (_resp->options & RES_USE_EDNS0)
_resp->options |= RES_USE_DNSSEC;
#endif /* RES_USE_DNSEC */
/* make query */
length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
answer, sizeof(answer));
if (length < 0) {
switch(h_errno) {
case HOST_NOT_FOUND:
result = ERRSET_NONAME;
goto fail;
case NO_DATA:
result = ERRSET_NODATA;
goto fail;
default:
result = ERRSET_FAIL;
goto fail;
}
}
/* parse result */
response = parse_dns_response(answer, length);
if (response == NULL) {
result = ERRSET_FAIL;
goto fail;
}
if (response->header.qdcount != 1) {
result = ERRSET_FAIL;
goto fail;
}
/* initialize rrset */
rrset = calloc(1, sizeof(struct rrsetinfo));
if (rrset == NULL) {
result = ERRSET_NOMEMORY;
goto fail;
}
rrset->rri_rdclass = response->query->class;
rrset->rri_rdtype = response->query->type;
rrset->rri_ttl = response->answer->ttl;
rrset->rri_nrdatas = response->header.ancount;
#ifdef HAVE_HEADER_AD
/* check for authenticated data */
if (response->header.ad == 1)
rrset->rri_flags |= RRSET_VALIDATED;
#endif
/* copy name from answer section */
rrset->rri_name = strdup(response->answer->name);
if (rrset->rri_name == NULL) {
result = ERRSET_NOMEMORY;
goto fail;
}
/* count answers */
rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
rrset->rri_rdtype);
rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
T_RRSIG);
/* allocate memory for answers */
rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
sizeof(struct rdatainfo));
if (rrset->rri_rdatas == NULL) {
result = ERRSET_NOMEMORY;
goto fail;
}
/* allocate memory for signatures */
if (rrset->rri_nsigs > 0) {
rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
if (rrset->rri_sigs == NULL) {
result = ERRSET_NOMEMORY;
goto fail;
}
}
/* copy answers & signatures */
for (rr = response->answer, index_ans = 0, index_sig = 0;
rr; rr = rr->next) {
rdata = NULL;
if (rr->class == rrset->rri_rdclass &&
rr->type == rrset->rri_rdtype)
rdata = &rrset->rri_rdatas[index_ans++];
if (rr->class == rrset->rri_rdclass &&
rr->type == T_RRSIG)
rdata = &rrset->rri_sigs[index_sig++];
if (rdata) {
rdata->rdi_length = rr->size;
rdata->rdi_data = malloc(rr->size);
if (rdata->rdi_data == NULL) {
result = ERRSET_NOMEMORY;
goto fail;
}
memcpy(rdata->rdi_data, rr->rdata, rr->size);
}
}
free_dns_response(response);
*res = rrset;
return (ERRSET_SUCCESS);
fail:
if (rrset != NULL)
freerrset(rrset);
if (response != NULL)
free_dns_response(response);
return (result);
}
void
freerrset(struct rrsetinfo *rrset)
{
u_int16_t i;
if (rrset == NULL)
return;
if (rrset->rri_rdatas) {
for (i = 0; i < rrset->rri_nrdatas; i++) {
if (rrset->rri_rdatas[i].rdi_data == NULL)
break;
free(rrset->rri_rdatas[i].rdi_data);
}
free(rrset->rri_rdatas);
}
if (rrset->rri_sigs) {
for (i = 0; i < rrset->rri_nsigs; i++) {
if (rrset->rri_sigs[i].rdi_data == NULL)
break;
free(rrset->rri_sigs[i].rdi_data);
}
free(rrset->rri_sigs);
}
if (rrset->rri_name)
free(rrset->rri_name);
free(rrset);
}
/*
* DNS response parsing routines
*/
static struct dns_response *
parse_dns_response(const u_char *answer, int size)
{
struct dns_response *resp;
const u_char *cp;
/* allocate memory for the response */
resp = calloc(1, sizeof(*resp));
if (resp == NULL)
return (NULL);
/* initialize current pointer */
cp = answer;
/* copy header */
memcpy(&resp->header, cp, HFIXEDSZ);
cp += HFIXEDSZ;
/* fix header byte order */
resp->header.qdcount = ntohs(resp->header.qdcount);
resp->header.ancount = ntohs(resp->header.ancount);
resp->header.nscount = ntohs(resp->header.nscount);
resp->header.arcount = ntohs(resp->header.arcount);
/* there must be at least one query */
if (resp->header.qdcount < 1) {
free_dns_response(resp);
return (NULL);
}
/* parse query section */
resp->query = parse_dns_qsection(answer, size, &cp,
resp->header.qdcount);
if (resp->header.qdcount && resp->query == NULL) {
free_dns_response(resp);
return (NULL);
}
/* parse answer section */
resp->answer = parse_dns_rrsection(answer, size, &cp,
resp->header.ancount);
if (resp->header.ancount && resp->answer == NULL) {
free_dns_response(resp);
return (NULL);
}
/* parse authority section */
resp->authority = parse_dns_rrsection(answer, size, &cp,
resp->header.nscount);
if (resp->header.nscount && resp->authority == NULL) {
free_dns_response(resp);
return (NULL);
}
/* parse additional section */
resp->additional = parse_dns_rrsection(answer, size, &cp,
resp->header.arcount);
if (resp->header.arcount && resp->additional == NULL) {
free_dns_response(resp);
return (NULL);
}
return (resp);
}
static struct dns_query *
parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
{
struct dns_query *head, *curr, *prev;
int i, length;
char name[MAXDNAME];
for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
/* allocate and initialize struct */
curr = calloc(1, sizeof(struct dns_query));
if (curr == NULL) {
free_dns_query(head);
return (NULL);
}
if (head == NULL)
head = curr;
if (prev != NULL)
prev->next = curr;
/* name */
length = dn_expand(answer, answer + size, *cp, name,
sizeof(name));
if (length < 0) {
free_dns_query(head);
return (NULL);
}
curr->name = strdup(name);
if (curr->name == NULL) {
free_dns_query(head);
return (NULL);
}
*cp += length;
/* type */
curr->type = _getshort(*cp);
*cp += INT16SZ;
/* class */
curr->class = _getshort(*cp);
*cp += INT16SZ;
}
return (head);
}
static struct dns_rr *
parse_dns_rrsection(const u_char *answer, int size, const u_char **cp,
int count)
{
struct dns_rr *head, *curr, *prev;
int i, length;
char name[MAXDNAME];
for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
/* allocate and initialize struct */
curr = calloc(1, sizeof(struct dns_rr));
if (curr == NULL) {
free_dns_rr(head);
return (NULL);
}
if (head == NULL)
head = curr;
if (prev != NULL)
prev->next = curr;
/* name */
length = dn_expand(answer, answer + size, *cp, name,
sizeof(name));
if (length < 0) {
free_dns_rr(head);
return (NULL);
}
curr->name = strdup(name);
if (curr->name == NULL) {
free_dns_rr(head);
return (NULL);
}
*cp += length;
/* type */
curr->type = _getshort(*cp);
*cp += INT16SZ;
/* class */
curr->class = _getshort(*cp);
*cp += INT16SZ;
/* ttl */
curr->ttl = _getlong(*cp);
*cp += INT32SZ;
/* rdata size */
curr->size = _getshort(*cp);
*cp += INT16SZ;
/* rdata itself */
curr->rdata = malloc(curr->size);
if (curr->rdata == NULL) {
free_dns_rr(head);
return (NULL);
}
memcpy(curr->rdata, *cp, curr->size);
*cp += curr->size;
}
return (head);
}
static void
free_dns_query(struct dns_query *p)
{
if (p == NULL)
return;
if (p->name)
free(p->name);
free_dns_query(p->next);
free(p);
}
static void
free_dns_rr(struct dns_rr *p)
{
if (p == NULL)
return;
if (p->name)
free(p->name);
if (p->rdata)
free(p->rdata);
free_dns_rr(p->next);
free(p);
}
static void
free_dns_response(struct dns_response *p)
{
if (p == NULL)
return;
free_dns_query(p->query);
free_dns_rr(p->answer);
free_dns_rr(p->authority);
free_dns_rr(p->additional);
free(p);
}
static int
count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
{
int n = 0;
while(p) {
if (p->class == class && p->type == type)
n++;
p = p->next;
}
return (n);
}
#endif /* !defined(HAVE_GETRRSETBYNAME) */

View File

@ -0,0 +1,110 @@
/* OPENBSD BASED ON : include/netdb.h */
/* $OpenBSD: getrrsetbyname.c,v 1.4 2001/08/16 18:16:43 ho Exp $ */
/*
* Copyright (c) 2001 Jakob Schlyter. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
/*
* Portions Copyright (c) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _GETRRSETBYNAME_H
#define _GETRRSETBYNAME_H
#include "includes.h"
#ifndef HAVE_GETRRSETBYNAME
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <resolv.h>
#ifndef HFIXEDSZ
#define HFIXEDSZ 12
#endif
#ifndef T_RRSIG
#define T_RRSIG 46
#endif
/*
* Flags for getrrsetbyname()
*/
#ifndef RRSET_VALIDATED
# define RRSET_VALIDATED 1
#endif
/*
* Return codes for getrrsetbyname()
*/
#ifndef ERRSET_SUCCESS
# define ERRSET_SUCCESS 0
# define ERRSET_NOMEMORY 1
# define ERRSET_FAIL 2
# define ERRSET_INVAL 3
# define ERRSET_NONAME 4
# define ERRSET_NODATA 5
#endif
struct rdatainfo {
unsigned int rdi_length; /* length of data */
unsigned char *rdi_data; /* record data */
};
struct rrsetinfo {
unsigned int rri_flags; /* RRSET_VALIDATED ... */
unsigned int rri_rdclass; /* class number */
unsigned int rri_rdtype; /* RR type number */
unsigned int rri_ttl; /* time to live */
unsigned int rri_nrdatas; /* size of rdatas array */
unsigned int rri_nsigs; /* size of sigs array */
char *rri_name; /* canonical name */
struct rdatainfo *rri_rdatas; /* individual records */
struct rdatainfo *rri_sigs; /* individual signatures */
};
int getrrsetbyname(const char *, unsigned int, unsigned int, unsigned int, struct rrsetinfo **);
void freerrset(struct rrsetinfo *);
#endif /* !defined(HAVE_GETRRSETBYNAME) */
#endif /* _GETRRSETBYNAME_H */

874
openbsd-compat/glob.c Normal file
View File

@ -0,0 +1,874 @@
/* $OpenBSD: glob.c,v 1.26 2005/11/28 17:50:12 deraadt Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* OPENBSD ORIGINAL: lib/libc/gen/glob.c */
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <ctype.h>
#include <errno.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \
!defined(GLOB_HAS_GL_MATCHC) || \
!defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \
defined(BROKEN_GLOB)
static long
get_arg_max(void)
{
#ifdef ARG_MAX
return(ARG_MAX);
#elif defined(HAVE_SYSCONF) && defined(_SC_ARG_MAX)
return(sysconf(_SC_ARG_MAX));
#else
return(256); /* XXX: arbitrary */
#endif
}
/*
* glob(3) -- a superset of the one defined in POSIX 1003.2.
*
* The [!...] convention to negate a range is supported (SysV, Posix, ksh).
*
* Optional extra services, controlled by flags not defined by POSIX:
*
* GLOB_QUOTE:
* Escaping convention: \ inhibits any special meaning the following
* character might have (except \ at end of string is retained).
* GLOB_MAGCHAR:
* Set in gl_flags if pattern contained a globbing character.
* GLOB_NOMAGIC:
* Same as GLOB_NOCHECK, but it will only append pattern if it did
* not contain any magic characters. [Used in csh style globbing]
* GLOB_ALTDIRFUNC:
* Use alternately specified directory access functions.
* GLOB_TILDE:
* expand ~user/foo to the /home/dir/of/user/foo
* GLOB_BRACE:
* expand {1,2}{a,b} to 1a 1b 2a 2b
* gl_matchc:
* Number of matches in the current invocation of glob.
*/
#define DOLLAR '$'
#define DOT '.'
#define EOS '\0'
#define LBRACKET '['
#define NOT '!'
#define QUESTION '?'
#define QUOTE '\\'
#define RANGE '-'
#define RBRACKET ']'
#define SEP '/'
#define STAR '*'
#undef TILDE /* Some platforms may already define it */
#define TILDE '~'
#define UNDERSCORE '_'
#define LBRACE '{'
#define RBRACE '}'
#define SLASH '/'
#define COMMA ','
#ifndef DEBUG
#define M_QUOTE 0x8000
#define M_PROTECT 0x4000
#define M_MASK 0xffff
#define M_ASCII 0x00ff
typedef u_short Char;
#else
#define M_QUOTE 0x80
#define M_PROTECT 0x40
#define M_MASK 0xff
#define M_ASCII 0x7f
typedef char Char;
#endif
#define CHAR(c) ((Char)((c)&M_ASCII))
#define META(c) ((Char)((c)|M_QUOTE))
#define M_ALL META('*')
#define M_END META(']')
#define M_NOT META('!')
#define M_ONE META('?')
#define M_RNG META('-')
#define M_SET META('[')
#define ismeta(c) (((c)&M_QUOTE) != 0)
static int compare(const void *, const void *);
static int g_Ctoc(const Char *, char *, u_int);
static int g_lstat(Char *, struct stat *, glob_t *);
static DIR *g_opendir(Char *, glob_t *);
static Char *g_strchr(Char *, int);
static int g_stat(Char *, struct stat *, glob_t *);
static int glob0(const Char *, glob_t *);
static int glob1(Char *, Char *, glob_t *, size_t *);
static int glob2(Char *, Char *, Char *, Char *, Char *, Char *,
glob_t *, size_t *);
static int glob3(Char *, Char *, Char *, Char *, Char *,
Char *, Char *, glob_t *, size_t *);
static int globextend(const Char *, glob_t *, size_t *);
static const Char *
globtilde(const Char *, Char *, size_t, glob_t *);
static int globexp1(const Char *, glob_t *);
static int globexp2(const Char *, const Char *, glob_t *, int *);
static int match(Char *, Char *, Char *);
#ifdef DEBUG
static void qprintf(const char *, Char *);
#endif
int
glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
glob_t *pglob)
{
const u_char *patnext;
int c;
Char *bufnext, *bufend, patbuf[MAXPATHLEN];
patnext = (u_char *) pattern;
if (!(flags & GLOB_APPEND)) {
pglob->gl_pathc = 0;
pglob->gl_pathv = NULL;
if (!(flags & GLOB_DOOFFS))
pglob->gl_offs = 0;
}
pglob->gl_flags = flags & ~GLOB_MAGCHAR;
pglob->gl_errfunc = errfunc;
pglob->gl_matchc = 0;
bufnext = patbuf;
bufend = bufnext + MAXPATHLEN - 1;
if (flags & GLOB_NOESCAPE)
while (bufnext < bufend && (c = *patnext++) != EOS)
*bufnext++ = c;
else {
/* Protect the quoted characters. */
while (bufnext < bufend && (c = *patnext++) != EOS)
if (c == QUOTE) {
if ((c = *patnext++) == EOS) {
c = QUOTE;
--patnext;
}
*bufnext++ = c | M_PROTECT;
} else
*bufnext++ = c;
}
*bufnext = EOS;
if (flags & GLOB_BRACE)
return globexp1(patbuf, pglob);
else
return glob0(patbuf, pglob);
}
/*
* Expand recursively a glob {} pattern. When there is no more expansion
* invoke the standard globbing routine to glob the rest of the magic
* characters
*/
static int
globexp1(const Char *pattern, glob_t *pglob)
{
const Char* ptr = pattern;
int rv;
/* Protect a single {}, for find(1), like csh */
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
return glob0(pattern, pglob);
while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
if (!globexp2(ptr, pattern, pglob, &rv))
return rv;
return glob0(pattern, pglob);
}
/*
* Recursive brace globbing helper. Tries to expand a single brace.
* If it succeeds then it invokes globexp1 with the new pattern.
* If it fails then it tries to glob the rest of the pattern and returns.
*/
static int
globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv)
{
int i;
Char *lm, *ls;
const Char *pe, *pm, *pl;
Char patbuf[MAXPATHLEN];
/* copy part up to the brace */
for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
;
*lm = EOS;
ls = lm;
/* Find the balanced brace */
for (i = 0, pe = ++ptr; *pe; pe++)
if (*pe == LBRACKET) {
/* Ignore everything between [] */
for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
;
if (*pe == EOS) {
/*
* We could not find a matching RBRACKET.
* Ignore and just look for RBRACE
*/
pe = pm;
}
} else if (*pe == LBRACE)
i++;
else if (*pe == RBRACE) {
if (i == 0)
break;
i--;
}
/* Non matching braces; just glob the pattern */
if (i != 0 || *pe == EOS) {
*rv = glob0(patbuf, pglob);
return 0;
}
for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
switch (*pm) {
case LBRACKET:
/* Ignore everything between [] */
for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
;
if (*pm == EOS) {
/*
* We could not find a matching RBRACKET.
* Ignore and just look for RBRACE
*/
pm = pl;
}
break;
case LBRACE:
i++;
break;
case RBRACE:
if (i) {
i--;
break;
}
/* FALLTHROUGH */
case COMMA:
if (i && *pm == COMMA)
break;
else {
/* Append the current string */
for (lm = ls; (pl < pm); *lm++ = *pl++)
;
/*
* Append the rest of the pattern after the
* closing brace
*/
for (pl = pe + 1; (*lm++ = *pl++) != EOS; )
;
/* Expand the current pattern */
#ifdef DEBUG
qprintf("globexp2:", patbuf);
#endif
*rv = globexp1(patbuf, pglob);
/* move after the comma, to the next string */
pl = pm + 1;
}
break;
default:
break;
}
}
*rv = 0;
return 0;
}
/*
* expand tilde from the passwd file.
*/
static const Char *
globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
{
struct passwd *pwd;
char *h;
const Char *p;
Char *b, *eb;
if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
return pattern;
/* Copy up to the end of the string or / */
eb = &patbuf[patbuf_len - 1];
for (p = pattern + 1, h = (char *) patbuf;
h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
;
*h = EOS;
#if 0
if (h == (char *)eb)
return what;
#endif
if (((char *) patbuf)[0] == EOS) {
/*
* handle a plain ~ or ~/ by expanding $HOME
* first and then trying the password file
*/
#if 0
if (issetugid() != 0 || (h = getenv("HOME")) == NULL) {
#endif
if ((getuid() != geteuid()) || (h = getenv("HOME")) == NULL) {
if ((pwd = getpwuid(getuid())) == NULL)
return pattern;
else
h = pwd->pw_dir;
}
} else {
/*
* Expand a ~user
*/
if ((pwd = getpwnam((char*) patbuf)) == NULL)
return pattern;
else
h = pwd->pw_dir;
}
/* Copy the home directory */
for (b = patbuf; b < eb && *h; *b++ = *h++)
;
/* Append the rest of the pattern */
while (b < eb && (*b++ = *p++) != EOS)
;
*b = EOS;
return patbuf;
}
/*
* The main glob() routine: compiles the pattern (optionally processing
* quotes), calls glob1() to do the real pattern matching, and finally
* sorts the list (unless unsorted operation is requested). Returns 0
* if things went well, nonzero if errors occurred. It is not an error
* to find no matches.
*/
static int
glob0(const Char *pattern, glob_t *pglob)
{
const Char *qpatnext;
int c, err, oldpathc;
Char *bufnext, patbuf[MAXPATHLEN];
size_t limit = 0;
qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
oldpathc = pglob->gl_pathc;
bufnext = patbuf;
/* We don't need to check for buffer overflow any more. */
while ((c = *qpatnext++) != EOS) {
switch (c) {
case LBRACKET:
c = *qpatnext;
if (c == NOT)
++qpatnext;
if (*qpatnext == EOS ||
g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
*bufnext++ = LBRACKET;
if (c == NOT)
--qpatnext;
break;
}
*bufnext++ = M_SET;
if (c == NOT)
*bufnext++ = M_NOT;
c = *qpatnext++;
do {
*bufnext++ = CHAR(c);
if (*qpatnext == RANGE &&
(c = qpatnext[1]) != RBRACKET) {
*bufnext++ = M_RNG;
*bufnext++ = CHAR(c);
qpatnext += 2;
}
} while ((c = *qpatnext++) != RBRACKET);
pglob->gl_flags |= GLOB_MAGCHAR;
*bufnext++ = M_END;
break;
case QUESTION:
pglob->gl_flags |= GLOB_MAGCHAR;
*bufnext++ = M_ONE;
break;
case STAR:
pglob->gl_flags |= GLOB_MAGCHAR;
/* collapse adjacent stars to one,
* to avoid exponential behavior
*/
if (bufnext == patbuf || bufnext[-1] != M_ALL)
*bufnext++ = M_ALL;
break;
default:
*bufnext++ = CHAR(c);
break;
}
}
*bufnext = EOS;
#ifdef DEBUG
qprintf("glob0:", patbuf);
#endif
if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0)
return(err);
/*
* If there was no match we are going to append the pattern
* if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
* and the pattern did not contain any magic characters
* GLOB_NOMAGIC is there just for compatibility with csh.
*/
if (pglob->gl_pathc == oldpathc) {
if ((pglob->gl_flags & GLOB_NOCHECK) ||
((pglob->gl_flags & GLOB_NOMAGIC) &&
!(pglob->gl_flags & GLOB_MAGCHAR)))
return(globextend(pattern, pglob, &limit));
else
return(GLOB_NOMATCH);
}
if (!(pglob->gl_flags & GLOB_NOSORT))
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
return(0);
}
static int
compare(const void *p, const void *q)
{
return(strcmp(*(char **)p, *(char **)q));
}
static int
glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp)
{
Char pathbuf[MAXPATHLEN];
/* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
if (*pattern == EOS)
return(0);
return(glob2(pathbuf, pathbuf+MAXPATHLEN-1,
pathbuf, pathbuf+MAXPATHLEN-1,
pattern, pattern_last, pglob, limitp));
}
/*
* The functions glob2 and glob3 are mutually recursive; there is one level
* of recursion for each segment in the pattern that contains one or more
* meta characters.
*/
static int
glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp)
{
struct stat sb;
Char *p, *q;
int anymeta;
/*
* Loop over pattern segments until end of pattern or until
* segment with meta character found.
*/
for (anymeta = 0;;) {
if (*pattern == EOS) { /* End of pattern? */
*pathend = EOS;
if (g_lstat(pathbuf, &sb, pglob))
return(0);
if (((pglob->gl_flags & GLOB_MARK) &&
pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
(S_ISLNK(sb.st_mode) &&
(g_stat(pathbuf, &sb, pglob) == 0) &&
S_ISDIR(sb.st_mode)))) {
if (pathend+1 > pathend_last)
return (1);
*pathend++ = SEP;
*pathend = EOS;
}
++pglob->gl_matchc;
return(globextend(pathbuf, pglob, limitp));
}
/* Find end of next segment, copy tentatively to pathend. */
q = pathend;
p = pattern;
while (*p != EOS && *p != SEP) {
if (ismeta(*p))
anymeta = 1;
if (q+1 > pathend_last)
return (1);
*q++ = *p++;
}
if (!anymeta) { /* No expansion, do next segment. */
pathend = q;
pattern = p;
while (*pattern == SEP) {
if (pathend+1 > pathend_last)
return (1);
*pathend++ = *pattern++;
}
} else
/* Need expansion, recurse. */
return(glob3(pathbuf, pathbuf_last, pathend,
pathend_last, pattern, p, pattern_last,
pglob, limitp));
}
/* NOTREACHED */
}
static int
glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob,
size_t *limitp)
{
struct dirent *dp;
DIR *dirp;
int err;
char buf[MAXPATHLEN];
/*
* The readdirfunc declaration can't be prototyped, because it is
* assigned, below, to two functions which are prototyped in glob.h
* and dirent.h as taking pointers to differently typed opaque
* structures.
*/
struct dirent *(*readdirfunc)(void *);
if (pathend > pathend_last)
return (1);
*pathend = EOS;
errno = 0;
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
/* TODO: don't call for ENOENT or ENOTDIR? */
if (pglob->gl_errfunc) {
if (g_Ctoc(pathbuf, buf, sizeof(buf)))
return(GLOB_ABORTED);
if (pglob->gl_errfunc(buf, errno) ||
pglob->gl_flags & GLOB_ERR)
return(GLOB_ABORTED);
}
return(0);
}
err = 0;
/* Search directory for matching names. */
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
readdirfunc = pglob->gl_readdir;
else
readdirfunc = (struct dirent *(*)(void *))readdir;
while ((dp = (*readdirfunc)(dirp))) {
u_char *sc;
Char *dc;
/* Initial DOT must be matched literally. */
if (dp->d_name[0] == DOT && *pattern != DOT)
continue;
dc = pathend;
sc = (u_char *) dp->d_name;
while (dc < pathend_last && (*dc++ = *sc++) != EOS)
;
if (dc >= pathend_last) {
*dc = EOS;
err = 1;
break;
}
if (!match(pathend, pattern, restpattern)) {
*pathend = EOS;
continue;
}
err = glob2(pathbuf, pathbuf_last, --dc, pathend_last,
restpattern, restpattern_last, pglob, limitp);
if (err)
break;
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
(*pglob->gl_closedir)(dirp);
else
closedir(dirp);
return(err);
}
/*
* Extend the gl_pathv member of a glob_t structure to accommodate a new item,
* add the new item, and update gl_pathc.
*
* This assumes the BSD realloc, which only copies the block when its size
* crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
* behavior.
*
* Return 0 if new item added, error code if memory couldn't be allocated.
*
* Invariant of the glob_t structure:
* Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
* gl_pathv points to (gl_offs + gl_pathc + 1) items.
*/
static int
globextend(const Char *path, glob_t *pglob, size_t *limitp)
{
char **pathv;
int i;
u_int newsize, len;
char *copy;
const Char *p;
newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) :
malloc(newsize);
if (pathv == NULL) {
if (pglob->gl_pathv) {
free(pglob->gl_pathv);
pglob->gl_pathv = NULL;
}
return(GLOB_NOSPACE);
}
if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
/* first time around -- clear initial gl_offs items */
pathv += pglob->gl_offs;
for (i = pglob->gl_offs; --i >= 0; )
*--pathv = NULL;
}
pglob->gl_pathv = pathv;
for (p = path; *p++;)
;
len = (size_t)(p - path);
*limitp += len;
if ((copy = malloc(len)) != NULL) {
if (g_Ctoc(path, copy, len)) {
free(copy);
return(GLOB_NOSPACE);
}
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
}
pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
if ((pglob->gl_flags & GLOB_LIMIT) &&
newsize + *limitp >= (u_int) get_arg_max()) {
errno = 0;
return(GLOB_NOSPACE);
}
return(copy == NULL ? GLOB_NOSPACE : 0);
}
/*
* pattern matching function for filenames. Each occurrence of the *
* pattern causes a recursion level.
*/
static int
match(Char *name, Char *pat, Char *patend)
{
int ok, negate_range;
Char c, k;
while (pat < patend) {
c = *pat++;
switch (c & M_MASK) {
case M_ALL:
if (pat == patend)
return(1);
do {
if (match(name, pat, patend))
return(1);
} while (*name++ != EOS);
return(0);
case M_ONE:
if (*name++ == EOS)
return(0);
break;
case M_SET:
ok = 0;
if ((k = *name++) == EOS)
return(0);
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
++pat;
while (((c = *pat++) & M_MASK) != M_END)
if ((*pat & M_MASK) == M_RNG) {
if (c <= k && k <= pat[1])
ok = 1;
pat += 2;
} else if (c == k)
ok = 1;
if (ok == negate_range)
return(0);
break;
default:
if (*name++ != c)
return(0);
break;
}
}
return(*name == EOS);
}
/* Free allocated data belonging to a glob_t structure. */
void
globfree(glob_t *pglob)
{
int i;
char **pp;
if (pglob->gl_pathv != NULL) {
pp = pglob->gl_pathv + pglob->gl_offs;
for (i = pglob->gl_pathc; i--; ++pp)
if (*pp)
free(*pp);
free(pglob->gl_pathv);
pglob->gl_pathv = NULL;
}
}
static DIR *
g_opendir(Char *str, glob_t *pglob)
{
char buf[MAXPATHLEN];
if (!*str)
pamsshagentauth_strlcpy(buf, ".", sizeof buf);
else {
if (g_Ctoc(str, buf, sizeof(buf)))
return(NULL);
}
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return((*pglob->gl_opendir)(buf));
return(opendir(buf));
}
static int
g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
{
char buf[MAXPATHLEN];
if (g_Ctoc(fn, buf, sizeof(buf)))
return(-1);
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return((*pglob->gl_lstat)(buf, sb));
return(lstat(buf, sb));
}
static int
g_stat(Char *fn, struct stat *sb, glob_t *pglob)
{
char buf[MAXPATHLEN];
if (g_Ctoc(fn, buf, sizeof(buf)))
return(-1);
if (pglob->gl_flags & GLOB_ALTDIRFUNC)
return((*pglob->gl_stat)(buf, sb));
return(stat(buf, sb));
}
static Char *
g_strchr(Char *str, int ch)
{
do {
if (*str == ch)
return (str);
} while (*str++);
return (NULL);
}
static int
g_Ctoc(const Char *str, char *buf, u_int len)
{
while (len--) {
if ((*buf++ = *str++) == EOS)
return (0);
}
return (1);
}
#ifdef DEBUG
static void
qprintf(const char *str, Char *s)
{
Char *p;
(void)printf("%s:\n", str);
for (p = s; *p; p++)
(void)printf("%c", CHAR(*p));
(void)printf("\n");
for (p = s; *p; p++)
(void)printf("%c", *p & M_PROTECT ? '"' : ' ');
(void)printf("\n");
for (p = s; *p; p++)
(void)printf("%c", ismeta(*p) ? '_' : ' ');
(void)printf("\n");
}
#endif
#endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) ||
!defined(GLOB_HAS_GL_MATCHC) */

100
openbsd-compat/glob.h Normal file
View File

@ -0,0 +1,100 @@
/* $OpenBSD: glob.h,v 1.10 2005/12/13 00:35:22 millert Exp $ */
/* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)glob.h 8.1 (Berkeley) 6/2/93
*/
/* OPENBSD ORIGINAL: include/glob.h */
#if !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || \
!defined(GLOB_HAS_GL_MATCHC) || \
!defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \
defined(BROKEN_GLOB)
#ifndef _GLOB_H_
#define _GLOB_H_
struct stat;
typedef struct {
int gl_pathc; /* Count of total paths so far. */
int gl_matchc; /* Count of paths matching pattern. */
int gl_offs; /* Reserved at beginning of gl_pathv. */
int gl_flags; /* Copy of flags parameter to glob. */
char **gl_pathv; /* List of paths matching pattern. */
/* Copy of errfunc parameter to glob. */
int (*gl_errfunc)(const char *, int);
/*
* Alternate filesystem access methods for glob; replacement
* versions of closedir(3), readdir(3), opendir(3), stat(2)
* and lstat(2).
*/
void (*gl_closedir)(void *);
struct dirent *(*gl_readdir)(void *);
void *(*gl_opendir)(const char *);
int (*gl_lstat)(const char *, struct stat *);
int (*gl_stat)(const char *, struct stat *);
} glob_t;
#define GLOB_APPEND 0x0001 /* Append to output from previous call. */
#define GLOB_DOOFFS 0x0002 /* Use gl_offs. */
#define GLOB_ERR 0x0004 /* Return on error. */
#define GLOB_MARK 0x0008 /* Append / to matching directories. */
#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
#define GLOB_NOSORT 0x0020 /* Don't sort. */
#define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */
/* Error values returned by glob(3) */
#define GLOB_NOSPACE (-1) /* Malloc call failed. */
#define GLOB_ABORTED (-2) /* Unignored error. */
#define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */
#define GLOB_NOSYS (-4) /* Function not supported. */
#define GLOB_ABEND GLOB_ABORTED
#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
#define GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
#define GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */
int glob(const char *, int, int (*)(const char *, int), glob_t *);
void globfree(glob_t *);
#endif /* !_GLOB_H_ */
#endif /* !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) ||
!defined(GLOB_HAS_GL_MATCHC */

179
openbsd-compat/inet_aton.c Normal file
View File

@ -0,0 +1,179 @@
/* $OpenBSD: inet_addr.c,v 1.9 2005/08/06 20:30:03 espie Exp $ */
/*
* Copyright (c) 1983, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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.
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
* --Copyright--
*/
/* OPENBSD ORIGINAL: lib/libc/net/inet_addr.c */
#include "includes.h"
#if !defined(HAVE_INET_ATON)
#include <sys/types.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#if 0
/*
* Ascii internet address interpretation routine.
* The value returned is in network order.
*/
in_addr_t
inet_addr(const char *cp)
{
struct in_addr val;
if (inet_aton(cp, &val))
return (val.s_addr);
return (INADDR_NONE);
}
#endif
/*
* Check whether "cp" is a valid ascii representation
* of an Internet address and convert to a binary address.
* Returns 1 if the address is valid, 0 if not.
* This replaces inet_addr, the return value from which
* cannot distinguish between failure and a local broadcast address.
*/
int
inet_aton(const char *cp, struct in_addr *addr)
{
u_int32_t val;
int base, n;
char c;
u_int parts[4];
u_int *pp = parts;
c = *cp;
for (;;) {
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, isdigit=decimal.
*/
if (!isdigit(c))
return (0);
val = 0; base = 10;
if (c == '0') {
c = *++cp;
if (c == 'x' || c == 'X')
base = 16, c = *++cp;
else
base = 8;
}
for (;;) {
if (isascii(c) && isdigit(c)) {
val = (val * base) + (c - '0');
c = *++cp;
} else if (base == 16 && isascii(c) && isxdigit(c)) {
val = (val << 4) |
(c + 10 - (islower(c) ? 'a' : 'A'));
c = *++cp;
} else
break;
}
if (c == '.') {
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
*/
if (pp >= parts + 3)
return (0);
*pp++ = val;
c = *++cp;
} else
break;
}
/*
* Check for trailing characters.
*/
if (c != '\0' && (!isascii(c) || !isspace(c)))
return (0);
/*
* Concoct the address according to
* the number of parts specified.
*/
n = pp - parts + 1;
switch (n) {
case 0:
return (0); /* initial nondigit */
case 1: /* a -- 32 bits */
break;
case 2: /* a.b -- 8.24 bits */
if ((val > 0xffffff) || (parts[0] > 0xff))
return (0);
val |= parts[0] << 24;
break;
case 3: /* a.b.c -- 8.8.16 bits */
if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff))
return (0);
val |= (parts[0] << 24) | (parts[1] << 16);
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
return (0);
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
break;
}
if (addr)
addr->s_addr = htonl(val);
return (1);
}
#endif /* !defined(HAVE_INET_ATON) */

View File

@ -0,0 +1,59 @@
/* $OpenBSD: inet_ntoa.c,v 1.6 2005/08/06 20:30:03 espie Exp $ */
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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.
*/
/* OPENBSD ORIGINAL: lib/libc/net/inet_ntoa.c */
#include "includes.h"
#if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA)
/*
* Convert network-format internet address
* to base 256 d.d.d.d representation.
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
char *
inet_ntoa(struct in_addr in)
{
static char b[18];
char *p;
p = (char *)&in;
#define UC(b) (((int)b)&0xff)
(void)snprintf(b, sizeof(b),
"%u.%u.%u.%u", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
return (b);
}
#endif /* defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) */

211
openbsd-compat/inet_ntop.c Normal file
View File

@ -0,0 +1,211 @@
/* $OpenBSD: inet_ntop.c,v 1.7 2005/08/06 20:30:03 espie Exp $ */
/* Copyright (c) 1996 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/* OPENBSD ORIGINAL: lib/libc/net/inet_ntop.c */
#include "includes.h"
#ifndef HAVE_INET_NTOP
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#ifndef IN6ADDRSZ
#define IN6ADDRSZ 16 /* IPv6 T_AAAA */
#endif
#ifndef INT16SZ
#define INT16SZ 2 /* for systems without 16-bit ints */
#endif
/*
* WARNING: Don't even consider trying to compile this on a system where
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
/* char *
* inet_ntop(af, src, dst, size)
* convert a network format address to presentation format.
* return:
* pointer to presentation format address (`dst'), or NULL (see errno).
* author:
* Paul Vixie, 1996.
*/
const char *
inet_ntop(int af, const void *src, char *dst, size_t size)
{
switch (af) {
case AF_INET:
return (inet_ntop4(src, dst, size));
case AF_INET6:
return (inet_ntop6(src, dst, size));
default:
errno = EAFNOSUPPORT;
return (NULL);
}
/* NOTREACHED */
}
/* const char *
* inet_ntop4(src, dst, size)
* format an IPv4 address, more or less like inet_ntoa()
* return:
* `dst' (as a const)
* notes:
* (1) uses no statics
* (2) takes a u_char* not an in_addr as input
* author:
* Paul Vixie, 1996.
*/
static const char *
inet_ntop4(const u_char *src, char *dst, size_t size)
{
static const char fmt[] = "%u.%u.%u.%u";
char tmp[sizeof "255.255.255.255"];
int l;
l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]);
if (l <= 0 || l >= size) {
errno = ENOSPC;
return (NULL);
}
pamsshagentauth_strlcpy(dst, tmp, size);
return (dst);
}
/* const char *
* inet_ntop6(src, dst, size)
* convert IPv6 binary address into presentation (printable) format
* author:
* Paul Vixie, 1996.
*/
static const char *
inet_ntop6(const u_char *src, char *dst, size_t size)
{
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
char *tp, *ep;
struct { int base, len; } best, cur;
u_int words[IN6ADDRSZ / INT16SZ];
int i;
int advance;
/*
* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
memset(words, '\0', sizeof words);
for (i = 0; i < IN6ADDRSZ; i++)
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
best.base = -1;
cur.base = -1;
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
if (words[i] == 0) {
if (cur.base == -1)
cur.base = i, cur.len = 1;
else
cur.len++;
} else {
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
}
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
}
if (best.base != -1 && best.len < 2)
best.base = -1;
/*
* Format the result.
*/
tp = tmp;
ep = tmp + sizeof(tmp);
for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
/* Are we inside the best run of 0x00's? */
if (best.base != -1 && i >= best.base &&
i < (best.base + best.len)) {
if (i == best.base) {
if (tp + 1 >= ep)
return (NULL);
*tp++ = ':';
}
continue;
}
/* Are we following an initial run of 0x00s or any real hex? */
if (i != 0) {
if (tp + 1 >= ep)
return (NULL);
*tp++ = ':';
}
/* Is this address an encapsulated IPv4? */
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
return (NULL);
tp += strlen(tp);
break;
}
advance = snprintf(tp, ep - tp, "%x", words[i]);
if (advance <= 0 || advance >= ep - tp)
return (NULL);
tp += advance;
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) {
if (tp + 1 >= ep)
return (NULL);
*tp++ = ':';
}
if (tp + 1 >= ep)
return (NULL);
*tp++ = '\0';
/*
* Check for overflow, copy, and we're done.
*/
if ((size_t)(tp - tmp) > size) {
errno = ENOSPC;
return (NULL);
}
pamsshagentauth_strlcpy(dst, tmp, size);
return (dst);
}
#endif /* !HAVE_INET_NTOP */

178
openbsd-compat/mktemp.c Normal file
View File

@ -0,0 +1,178 @@
/* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */
/* Changes: Removed mktemp */
/* $OpenBSD: mktemp.c,v 1.19 2005/08/08 08:05:36 espie Exp $ */
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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.
*/
/* OPENBSD ORIGINAL: lib/libc/stdio/mktemp.c */
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP)
static int _gettemp(char *, int *, int, int);
int
mkstemps(char *path, int slen)
{
int fd;
return (_gettemp(path, &fd, 0, slen) ? fd : -1);
}
int
mkstemp(char *path)
{
int fd;
return (_gettemp(path, &fd, 0, 0) ? fd : -1);
}
char *
mkdtemp(char *path)
{
return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
}
static int
_gettemp(path, doopen, domkdir, slen)
char *path;
register int *doopen;
int domkdir;
int slen;
{
register char *start, *trv, *suffp;
struct stat sbuf;
int rval;
pid_t pid;
if (doopen && domkdir) {
errno = EINVAL;
return(0);
}
for (trv = path; *trv; ++trv)
;
trv -= slen;
suffp = trv;
--trv;
if (trv < path) {
errno = EINVAL;
return (0);
}
pid = getpid();
while (trv >= path && *trv == 'X' && pid != 0) {
*trv-- = (pid % 10) + '0';
pid /= 10;
}
while (trv >= path && *trv == 'X') {
char c;
pid = (pamsshagentauth_arc4random() & 0xffff) % (26+26);
if (pid < 26)
c = pid + 'A';
else
c = (pid - 26) + 'a';
*trv-- = c;
}
start = trv + 1;
/*
* check the target directory; if you have six X's and it
* doesn't exist this runs for a *very* long time.
*/
if (doopen || domkdir) {
for (;; --trv) {
if (trv <= path)
break;
if (*trv == '/') {
*trv = '\0';
rval = stat(path, &sbuf);
*trv = '/';
if (rval != 0)
return(0);
if (!S_ISDIR(sbuf.st_mode)) {
errno = ENOTDIR;
return(0);
}
break;
}
}
}
for (;;) {
if (doopen) {
if ((*doopen =
open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
return(1);
if (errno != EEXIST)
return(0);
} else if (domkdir) {
if (mkdir(path, 0700) == 0)
return(1);
if (errno != EEXIST)
return(0);
} else if (lstat(path, &sbuf))
return(errno == ENOENT ? 1 : 0);
/* tricky little algorithm for backward compatibility */
for (trv = start;;) {
if (!*trv)
return (0);
if (*trv == 'Z') {
if (trv == suffp)
return (0);
*trv++ = 'a';
} else {
if (isdigit(*trv))
*trv = 'a';
else if (*trv == 'z') /* inc from z to A */
*trv = 'A';
else {
if (trv == suffp)
return (0);
++*trv;
}
break;
}
}
}
/*NOTREACHED*/
}
#endif /* !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) */

View File

@ -0,0 +1,215 @@
/* $Id: openbsd-compat.h,v 1.43 2007/06/25 12:15:13 dtucker Exp $ */
/*
* Copyright (c) 1999-2003 Damien Miller. All rights reserved.
* Copyright (c) 2003 Ben Lindstrom. All rights reserved.
* Copyright (c) 2002 Tim Rice. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _OPENBSD_COMPAT_H
#define _OPENBSD_COMPAT_H
#include "includes.h"
#include <sys/types.h>
#include <pwd.h>
#include <sys/socket.h>
/* OpenBSD function replacements */
#include "base64.h"
#include "sigact.h"
#include "glob.h"
#include "vis.h"
#include "getrrsetbyname.h"
#include "sha2.h"
#ifndef HAVE_BASENAME
char *basename(const char *path);
#endif
#ifndef HAVE_BINDRESVPORT_SA
int bindresvport_sa(int sd, struct sockaddr *sa);
#endif
#ifndef HAVE_CLOSEFROM
void closefrom(int);
#endif
#ifndef HAVE_GETCWD
char *getcwd(char *pt, size_t size);
#endif
#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH)
char *realpath(const char *path, char *resolved);
#endif
#ifndef HAVE_RRESVPORT_AF
int rresvport_af(int *alport, sa_family_t af);
#endif
#ifndef HAVE_STRLCPY
/* #include <sys/types.h> XXX Still needed? */
size_t pamsshagentauth_strlcpy(char *dst, const char *src, size_t siz);
#else
#define pamsshagentauth_strlcpy strlcpy
#endif
#ifndef HAVE_STRLCAT
/* #include <sys/types.h> XXX Still needed? */
size_t pamsshagentauth_strlcat(char *dst, const char *src, size_t siz);
#else
#define pamsshagentauth_strlcat strlcat
#endif
#ifndef HAVE_SETENV
int setenv(register const char *name, register const char *value, int rewrite);
#endif
#ifndef HAVE_STRMODE
void strmode(int mode, char *p);
#endif
#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP)
int mkstemps(char *path, int slen);
int mkstemp(char *path);
char *mkdtemp(char *path);
#endif
#ifndef HAVE_DAEMON
int daemon(int nochdir, int noclose);
#endif
#ifndef HAVE_DIRNAME
char *dirname(const char *path);
#endif
#if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA)
char *inet_ntoa(struct in_addr in);
#endif
#ifndef HAVE_INET_NTOP
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
#endif
#ifndef HAVE_INET_ATON
int inet_aton(const char *cp, struct in_addr *addr);
#endif
#ifndef HAVE_STRSEP
char *strsep(char **stringp, const char *delim);
#endif
#ifndef HAVE_SETPROCTITLE
void setproctitle(const char *fmt, ...);
void compat_init_setproctitle(int argc, char *argv[]);
#endif
#ifndef HAVE_GETGROUPLIST
/* #include <grp.h> XXXX Still needed ? */
int getgrouplist(const char *, gid_t, gid_t *, int *);
#endif
#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET)
int BSDgetopt(int argc, char * const *argv, const char *opts);
#endif
#if defined(HAVE_DECL_WRITEV) && HAVE_DECL_WRITEV == 0
# include <sys/types.h>
# include <sys/uio.h>
int writev(int, struct iovec *, int);
#endif
/* Home grown routines */
#include "bsd-misc.h"
#include "bsd-waitpid.h"
#include "bsd-poll.h"
#ifndef HAVE_GETPEEREID
int getpeereid(int , uid_t *, gid_t *);
#endif
#ifndef HAVE_ARC4RANDOM
unsigned int pamsshagentauth_arc4random(void);
void pamsshagentauth_arc4random_stir(void);
#else
#define pamsshagentauth_arc4random arc4random
#define pamsshagentauth_arc4random_stir arc4random_stir
#endif /* !HAVE_ARC4RANDOM */
#ifndef HAVE_ASPRINTF
int asprintf(char **, const char *, ...);
#endif
#ifndef HAVE_OPENPTY
# include <sys/ioctl.h> /* for struct winsize */
int openpty(int *, int *, char *, struct termios *, struct winsize *);
#endif /* HAVE_OPENPTY */
/* #include <sys/types.h> XXX needed? For size_t */
#ifndef HAVE_SNPRINTF
int snprintf(char *, size_t, SNPRINTF_CONST char *, ...);
#endif
#ifndef HAVE_STRTOLL
long long strtoll(const char *, char **, int);
#endif
#ifndef HAVE_STRTONUM
long long pamsshagentauth_strtonum(const char *, long long, long long, const char **);
#else
#define pamsshagentauth_strtonum strtonum
#endif
#if !defined(HAVE_VASPRINTF) || !defined(HAVE_VSNPRINTF)
# include <stdarg.h>
#endif
#ifndef HAVE_VASPRINTF
int vasprintf(char **, const char *, va_list);
#endif
#ifndef HAVE_VSNPRINTF
int vsnprintf(char *, size_t, const char *, va_list);
#endif
void *xmmap(size_t size);
char *xcrypt(const char *password, const char *salt);
char *shadow_pw(struct passwd *pw);
/* rfc2553 socket API replacements */
#include "fake-rfc2553.h"
/* Routines for a single OS platform */
#include "bsd-cray.h"
#include "bsd-cygwin_util.h"
#include "port-aix.h"
#include "port-irix.h"
#include "port-linux.h"
#include "port-solaris.h"
//#include "port-tun.h"
#include "port-uw.h"
#endif /* _OPENBSD_COMPAT_H */

Some files were not shown because too many files have changed in this diff Show More