Import NetBSD Secure Shell. This is based on OpenSSH, but modified

somewhat.
This commit is contained in:
thorpej 2000-09-28 22:09:28 +00:00
parent 03aaa05985
commit 49a55a1d58
117 changed files with 37623 additions and 0 deletions

136
crypto/dist/ssh/LICENCE vendored Normal file
View File

@ -0,0 +1,136 @@
This file is part of the ssh software.
The licences which components of this software falls under are as
follows. First, we will summarize and say that 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, ie.
- RSA is no longer included, found in the OpenSSL library
- IDEA is no longer included, it's use is depricated
- 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 implementation in crc32.c is due to Gary S. Brown.
Comments in the file indicate it may be used for any purpose without
restrictions:
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
3)
The 32-bit CRC compensation attack detector in deattack.c was
contributed by CORE SDI S.A. under a BSD-style license. See
http://www.core-sdi.com/english/ssh/ for details.
* 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>
4)
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
* 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.

164
crypto/dist/ssh/OVERVIEW vendored Normal file
View File

@ -0,0 +1,164 @@
This document is intended for those who wish to read the ssh source
code. This tries to give an overview of the structure of the code.
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>
Updated 17 Nov 1995.
Updated 19 Oct 1999 for OpenSSH-1.2
The software consists of ssh (client), sshd (server), scp, sdist, and
the auxiliary programs ssh-keygen, ssh-agent, ssh-add, and
make-ssh-known-hosts. The main program for each of these is in a .c
file with the same name.
There are some subsystems/abstractions that are used by a number of
these programs.
Buffer manipulation routines
- These provide an arbitrary size buffer, where data can be appended.
Data can be consumed from either end. The code is used heavily
throughout ssh. The basic buffer manipulation functions are in
buffer.c (header buffer.h), and additional code to manipulate specific
data types is in bufaux.c.
Compression Library
- Ssh uses the GNU GZIP compression library (ZLIB).
Encryption/Decryption
- Ssh contains several encryption algorithms. These are all
accessed through the cipher.h interface. The interface code is
in cipher.c, and the implementations are in libc.
Multiple Precision Integer Library
- Uses the SSLeay BIGNUM sublibrary.
- Some auxiliary functions for mp-int manipulation are in mpaux.c.
Random Numbers
- Uses arc4random() and such.
RSA key generation, encryption, decryption
- Ssh uses the RSA routines in libssl.
RSA key files
- RSA keys are stored in files with a special format. The code to
read/write these files is in authfile.c. The files are normally
encrypted with a passphrase. The functions to read passphrases
are in readpass.c (the same code is used to read passwords).
Binary packet protocol
- The ssh binary packet protocol is implemented in packet.c. The
code in packet.c does not concern itself with packet types or their
execution; it contains code to build packets, to receive them and
extract data from them, and the code to compress and/or encrypt
packets. CRC code comes from crc32.c.
- The code in packet.c calls the buffer manipulation routines
(buffer.c, bufaux.c), compression routines (compress.c, zlib),
and the encryption routines.
X11, TCP/IP, and Agent forwarding
- Code for various types of channel forwarding is in channels.c.
The file defines a generic framework for arbitrary communication
channels inside the secure channel, and uses this framework to
implement X11 forwarding, TCP/IP forwarding, and authentication
agent forwarding.
The new, Protocol 1.5, channel close implementation is in nchan.c
Authentication agent
- Code to communicate with the authentication agent is in authfd.c.
Authentication methods
- Code for various authentication methods resides in auth-*.c
(auth-passwd.c, auth-rh-rsa.c, auth-rhosts.c, auth-rsa.c). This
code is linked into the server. The routines also manipulate
known hosts files using code in hostfile.c. Code in canohost.c
is used to retrieve the canonical host name of the remote host.
Code in match.c is used to match host names.
- In the client end, authentication code is in sshconnect.c. It
reads Passwords/passphrases using code in readpass.c. It reads
RSA key files with authfile.c. It communicates the
authentication agent using authfd.c.
The ssh client
- The client main program is in ssh.c. It first parses arguments
and reads configuration (readconf.c), then calls ssh_connect (in
sshconnect.c) to open a connection to the server (possibly via a
proxy), and performs authentication (ssh_login in sshconnect.c).
It then makes any pty, forwarding, etc. requests. It may call
code in ttymodes.c to encode current tty modes. Finally it
calls client_loop in clientloop.c. This does the real work for
the session.
- The client is suid root. It tries to temporarily give up this
rights while reading the configuration data. The root
privileges are only used to make the connection (from a
privileged socket). Any extra privileges are dropped before
calling ssh_login.
Pseudo-tty manipulation and tty modes
- Code to allocate and use a pseudo tty is in pty.c. Code to
encode and set terminal modes is in ttymodes.c.
Logging in (updating utmp, lastlog, etc.)
- The code to do things that are done when a user logs in are in
login.c. This includes things such as updating the utmp, wtmp,
and lastlog files. Some of the code is in sshd.c.
Writing to the system log and terminal
- The programs use the functions fatal(), log(), debug(), error()
in many places to write messages to system log or user's
terminal. The implementation that logs to system log is in
log-server.c; it is used in the server program. The other
programs use an implementation that sends output to stderr; it
is in log-client.c. The definitions are in ssh.h.
The sshd server (daemon)
- The sshd daemon starts by processing arguments and reading the
configuration file (servconf.c). It then reads the host key,
starts listening for connections, and generates the server key.
The server key will be regenerated every hour by an alarm.
- When the server receives a connection, it forks, disables the
regeneration alarm, and starts communicating with the client.
They first perform identification string exchange, then
negotiate encryption, then perform authentication, preparatory
operations, and finally the server enters the normal session
mode by calling server_loop in serverloop.c. This does the real
work, calling functions in other modules.
- The code for the server is in sshd.c. It contains a lot of
stuff, including:
- server main program
- waiting for connections
- processing new connection
- authentication
- preparatory operations
- building up the execution environment for the user program
- starting the user program.
Auxiliary files
- There are several other files in the distribution that contain
various auxiliary routines:
ssh.h the main header file for ssh (various definitions)
getput.h byte-order independent storage of integers
includes.h includes most system headers. Lots of #ifdefs.
tildexpand.c expand tilde in file names
uidswap.c uid-swapping
xmalloc.c "safe" malloc routines

567
crypto/dist/ssh/README vendored Normal file
View File

@ -0,0 +1,567 @@
[ Please note that this file has not been updated for OpenSSH and
covers the ssh-1.2.12 release from Dec 1995 only. ]
Ssh (Secure Shell) is a program to log into another computer over a
network, to execute commands in a remote machine, and to move files
from one machine to another. It provides strong authentication and
secure communications over insecure channels. It is intended as a
replacement for rlogin, rsh, rcp, and rdist.
See the file INSTALL for installation instructions. See COPYING for
license terms and other legal issues. See RFC for a description of
the protocol. There is a WWW page for ssh; see http://www.cs.hut.fi/ssh.
This file has been updated to match ssh-1.2.12.
FEATURES
o Strong authentication. Closes several security holes (e.g., IP,
routing, and DNS spoofing). New authentication methods: .rhosts
together with RSA based host authentication, and pure RSA
authentication.
o Improved privacy. All communications are automatically and
transparently encrypted. RSA is used for key exchange, and a
conventional cipher (normally IDEA, DES, or triple-DES) for
encrypting the session. Encryption is started before
authentication, and no passwords or other information is
transmitted in the clear. Encryption is also used to protect
against spoofed packets.
o Secure X11 sessions. The program automatically sets DISPLAY on
the server machine, and forwards any X11 connections over the
secure channel. Fake Xauthority information is automatically
generated and forwarded to the remote machine; the local client
automatically examines incoming X11 connections and replaces the
fake authorization data with the real data (never telling the
remote machine the real information).
o Arbitrary TCP/IP ports can be redirected through the encrypted channel
in both directions (e.g., for e-cash transactions).
o No retraining needed for normal users; everything happens
automatically, and old .rhosts files will work with strong
authentication if administration installs host key files.
o Never trusts the network. Minimal trust on the remote side of
the connection. Minimal trust on domain name servers. Pure RSA
authentication never trusts anything but the private key.
o Client RSA-authenticates the server machine in the beginning of
every connection to prevent trojan horses (by routing or DNS
spoofing) and man-in-the-middle attacks, and the server
RSA-authenticates the client machine before accepting .rhosts or
/etc/hosts.equiv authentication (to prevent DNS, routing, or
IP-spoofing).
o Host authentication key distribution can be centrally by the
administration, automatically when the first connection is made
to a machine (the key obtained on the first connection will be
recorded and used for authentication in the future), or manually
by each user for his/her own use. The central and per-user host
key repositories are both used and complement each other. Host
keys can be generated centrally or automatically when the software
is installed. Host authentication keys are typically 1024 bits.
o Any user can create any number of user authentication RSA keys for
his/her own use. Each user has a file which lists the RSA public
keys for which proof of possession of the corresponding private
key is accepted as authentication. User authentication keys are
typically 1024 bits.
o The server program has its own server RSA key which is
automatically regenerated every hour. This key is never saved in
any file. Exchanged session keys are encrypted using both the
server key and the server host key. The purpose of the separate
server key is to make it impossible to decipher a captured session by
breaking into the server machine at a later time; one hour from
the connection even the server machine cannot decipher the session
key. The key regeneration interval is configurable. The server
key is normally 768 bits.
o An authentication agent, running in the user's laptop or local
workstation, can be used to hold the user's RSA authentication
keys. Ssh automatically forwards the connection to the
authentication agent over any connections, and there is no need to
store the RSA authentication keys on any machine in the network
(except the user's own local machine). The authentication
protocols never reveal the keys; they can only be used to verify
that the user's agent has a certain key. Eventually the agent
could rely on a smart card to perform all authentication
computations.
o The software can be installed and used (with restricted
functionality) even without root privileges.
o The client is customizable in system-wide and per-user
configuration files. Most aspects of the client's operation can
be configured. Different options can be specified on a per-host basis.
o Automatically executes conventional rsh (after displaying a
warning) if the server machine is not running sshd.
o Optional compression of all data with gzip (including forwarded X11
and TCP/IP port data), which may result in significant speedups on
slow connections.
o Complete replacement for rlogin, rsh, and rcp.
WHY TO USE SECURE SHELL
Currently, almost all communications in computer networks are done
without encryption. As a consequence, anyone who has access to any
machine connected to the network can listen in on any communication.
This is being done by hackers, curious administrators, employers,
criminals, industrial spies, and governments. Some networks leak off
enough electromagnetic radiation that data may be captured even from a
distance.
When you log in, your password goes in the network in plain
text. Thus, any listener can then use your account to do any evil he
likes. Many incidents have been encountered worldwide where crackers
have started programs on workstations without the owners knowledge
just to listen to the network and collect passwords. Programs for
doing this are available on the Internet, or can be built by a
competent programmer in a few hours.
Any information that you type or is printed on your screen can be
monitored, recorded, and analyzed. For example, an intruder who has
penetrated a host connected to a major network can start a program
that listens to all data flowing in the network, and whenever it
encounters a 16-digit string, it checks if it is a valid credit card
number (using the check digit), and saves the number plus any
surrounding text (to catch expiration date and holder) in a file.
When the intruder has collected a few thousand credit card numbers, he
makes smallish mail-order purchases from a few thousand stores around
the world, and disappears when the goods arrive but before anyone
suspects anything.
Businesses have trade secrets, patent applications in preparation,
pricing information, subcontractor information, client data, personnel
data, financial information, etc. Currently, anyone with access to
the network (any machine on the network) can listen to anything that
goes in the network, without any regard to normal access restrictions.
Many companies are not aware that information can so easily be
recovered from the network. They trust that their data is safe
since nobody is supposed to know that there is sensitive information
in the network, or because so much other data is transferred in the
network. This is not a safe policy.
Individual persons also have confidential information, such as
diaries, love letters, health care documents, information about their
personal interests and habits, professional data, job applications,
tax reports, political documents, unpublished manuscripts, etc.
One should also be aware that economical intelligence and industrial
espionage has recently become a major priority of the intelligence
agencies of major governments. President Clinton recently assigned
economical espionage as the primary task of the CIA, and the French
have repeatedly been publicly boasting about their achievements on
this field.
There is also another frightening aspect about the poor security of
communications. Computer storage and analysis capability has
increased so much that it is feasible for governments, major
companies, and criminal organizations to automatically analyze,
identify, classify, and file information about millions of people over
the years. Because most of the work can be automated, the cost of
collecting this information is getting very low.
Government agencies may be able to monitor major communication
systems, telephones, fax, computer networks, etc., and passively
collect huge amounts of information about all people with any
significant position in the society. Most of this information is not
sensitive, and many people would say there is no harm in someone
getting that information. However, the information starts to get
sensitive when someone has enough of it. You may not mind someone
knowing what you bought from the shop one random day, but you might
not like someone knowing every small thing you have bought in the last
ten years.
If the government some day starts to move into a more totalitarian
direction (one should remember that Nazi Germany was created by
democratic elections), there is considerable danger of an ultimate
totalitarian state. With enough information (the automatically
collected records of an individual can be manually analyzed when the
person becomes interesting), one can form a very detailed picture of
the individual's interests, opinions, beliefs, habits, friends,
lovers, weaknesses, etc. This information can be used to 1) locate
any persons who might oppose the new system 2) use deception to
disturb any organizations which might rise against the government 3)
eliminate difficult individuals without anyone understanding what
happened. Additionally, if the government can monitor communications
too effectively, it becomes too easy to locate and eliminate any
persons distributing information contrary to the official truth.
Fighting crime and terrorism are often used as grounds for domestic
surveillance and restricting encryption. These are good goals, but
there is considerable danger that the surveillance data starts to get
used for questionable purposes. I find that it is better to tolerate
a small amount of crime in the society than to let the society become
fully controlled. I am in favor of a fairly strong state, but the
state must never get so strong that people become unable to spread
contra-offical information and unable to overturn the government if it
is bad. The danger is that when you notice that the government is
too powerful, it is too late. Also, the real power may not be where
the official government is.
For these reasons (privacy, protecting trade secrets, and making it
more difficult to create a totalitarian state), I think that strong
cryptography should be integrated to the tools we use every day.
Using it causes no harm (except for those who wish to monitor
everything), but not using it can cause huge problems. If the society
changes in undesirable ways, then it will be to late to start
encrypting.
Encryption has had a "military" or "classified" flavor to it. There
are no longer any grounds for this. The military can and will use its
own encryption; that is no excuse to prevent the civilians from
protecting their privacy and secrets. Information on strong
encryption is available in every major bookstore, scientific library,
and patent office around the world, and strong encryption software is
available in every country on the Internet.
Some people would like to make it illegal to use encryption, or to
force people to use encryption that governments can break. This
approach offers no protection if the government turns bad. Also, the
"bad guys" will be using true strong encryption anyway. Good
encryption techniques are too widely known to make them disappear.
Thus, any "key escrow encryption" or other restrictions will only help
monitor ordinary people and petty criminals. It does not help against
powerful criminals, terrorists, or espionage, because they will know
how to use strong encryption anyway. (One source for internationally
available encryption software is http://www.cs.hut.fi/crypto.)
OVERVIEW OF SECURE SHELL
The software consists of a number of programs.
sshd Server program run on the server machine. This
listens for connections from client machines, and
whenever it receives a connection, it performs
authentication and starts serving the client.
ssh This is the client program used to log into another
machine or to execute commands on the other machine.
"slogin" is another name for this program.
scp Securely copies files from one machine to another.
ssh-keygen Used to create RSA keys (host keys and user
authentication keys).
ssh-agent Authentication agent. This can be used to hold RSA
keys for authentication.
ssh-add Used to register new keys with the agent.
make-ssh-known-hosts
Used to create the /etc/ssh_known_hosts file.
Ssh is the program users normally use. It is started as
ssh host
or
ssh host command
The first form opens a new shell on the remote machine (after
authentication). The latter form executes the command on the remote
machine.
When started, the ssh connects sshd on the server machine, verifies
that the server machine really is the machine it wanted to connect,
exchanges encryption keys (in a manner which prevents an outside
listener from getting the keys), performs authentication using .rhosts
and /etc/hosts.equiv, RSA authentication, or conventional password
based authentication. The server then (normally) allocates a
pseudo-terminal and starts an interactive shell or user program.
The TERM environment variable (describing the type of the user's
terminal) is passed from the client side to the remote side. Also,
terminal modes will be copied from the client side to the remote side
to preserve user preferences (e.g., the erase character).
If the DISPLAY variable is set on the client side, the server will
create a dummy X server and set DISPLAY accordingly. Any connections
to the dummy X server will be forwarded through the secure channel,
and will be made to the real X server from the client side. An
arbitrary number of X programs can be started during the session, and
starting them does not require anything special from the user. (Note
that the user must not manually set DISPLAY, because then it would
connect directly to the real display instead of going through the
encrypted channel). This behavior can be disabled in the
configuration file or by giving the -x option to the client.
Arbitrary IP ports can be forwarded over the secure channel. The
program then creates a port on one side, and whenever a connection is
opened to this port, it will be passed over the secure channel, and a
connection will be made from the other side to a specified host:port
pair. Arbitrary IP forwarding must always be explicitly requested,
and cannot be used to forward privileged ports (unless the user is
root). It is possible to specify automatic forwards in a per-user
configuration file, for example to make electronic cash systems work
securely.
If there is an authentication agent on the client side, connection to
it will be automatically forwarded to the server side.
For more infomation, see the manual pages ssh(1), sshd(8), scp(1),
ssh-keygen(1), ssh-agent(1), ssh-add(1), and make-ssh-known-hosts(1)
included in this distribution.
X11 CONNECTION FORWARDING
X11 forwarding serves two purposes: it is a convenience to the user
because there is no need to set the DISPLAY variable, and it provides
encrypted X11 connections. I cannot think of any other easy way to
make X11 connections encrypted; modifying the X server, clients or
libraries would require special work for each machine, vendor and
application. Widely used IP-level encryption does not seem likely for
several years. Thus what we have left is faking an X server on the
same machine where the clients are run, and forwarding the connections
to a real X server over the secure channel.
X11 forwarding works as follows. The client extracts Xauthority
information for the server. It then creates random authorization
data, and sends the random data to the server. The server allocates
an X11 display number, and stores the (fake) Xauthority data for this
display. Whenever an X11 connection is opened, the server forwards
the connection over the secure channel to the client, and the client
parses the first packet of the X11 protocol, substitutes real
authentication data for the fake data (if the fake data matched), and
forwards the connection to the real X server.
If the display does not have Xauthority data, the server will create a
unix domain socket in /tmp/.X11-unix, and use the unix domain socket
as the display. No authentication information is forwarded in this
case. X11 connections are again forwarded over the secure channel.
To the X server the connections appear to come from the client
machine, and the server must have connections allowed from the local
machine. Using authentication data is always recommended because not
using it makes the display insecure. If XDM is used, it automatically
generates the authentication data.
One should be careful not to use "xin" or "xstart" or other similar
scripts that explicitly set DISPLAY to start X sessions in a remote
machine, because the connection will then not go over the secure
channel. The recommended way to start a shell in a remote machine is
xterm -e ssh host &
and the recommended way to execute an X11 application in a remote
machine is
ssh -n host emacs &
If you need to type a password/passphrase for the remote machine,
ssh -f host emacs
may be useful.
RSA AUTHENTICATION
RSA authentication is based on public key cryptograpy. The idea is
that there are two encryption keys, one for encryption and another for
decryption. It is not possible (on human timescale) to derive the
decryption key from the encryption key. The encryption key is called
the public key, because it can be given to anyone and it is not
secret. The decryption key, on the other hand, is secret, and is
called the private key.
RSA authentication is based on the impossibility of deriving the
private key from the public key. The public key is stored on the
server machine in the user's $HOME/.ssh/authorized_keys file. The
private key is only kept on the user's local machine, laptop, or other
secure storage. Then the user tries to log in, the client tells the
server the public key that the user wishes to use for authentication.
The server then checks if this public key is admissible. If so, it
generates a 256 bit random number, encrypts it with the public key,
and sends the value to the client. The client then decrypts the
number with its private key, computes a 128 bit MD5 checksum from the
resulting data, and sends the checksum back to the server. (Only a
checksum is sent to prevent chosen-plaintext attacks against RSA.)
The server checks computes a checksum from the correct data,
and compares the checksums. Authentication is accepted if the
checksums match. (Theoretically this indicates that the client
only probably knows the correct key, but for all practical purposes
there is no doubt.)
The RSA private key can be protected with a passphrase. The
passphrase can be any string; it is hashed with MD5 to produce an
encryption key for IDEA, which is used to encrypt the private part of
the key file. With passphrase, authorization requires access to the key
file and the passphrase. Without passphrase, authorization only
depends on possession of the key file.
RSA authentication is the most secure form of authentication supported
by this software. It does not rely on the network, routers, domain
name servers, or the client machine. The only thing that matters is
access to the private key.
All this, of course, depends on the security of the RSA algorithm
itself. RSA has been widely known since about 1978, and no effective
methods for breaking it are known if it is used properly. Care has
been taken to avoid the well-known pitfalls. Breaking RSA is widely
believed to be equivalent to factoring, which is a very hard
mathematical problem that has received considerable public research.
So far, no effective methods are known for numbers bigger than about
512 bits. However, as computer speeds and factoring methods are
increasing, 512 bits can no longer be considered secure. The
factoring work is exponential, and 768 or 1024 bits are widely
considered to be secure in the near future.
RHOSTS AUTHENTICATION
Conventional .rhosts and hosts.equiv based authentication mechanisms
are fundamentally insecure due to IP, DNS (domain name server) and
routing spoofing attacks. Additionally this authentication method
relies on the integrity of the client machine. These weaknesses is
tolerable, and been known and exploited for a long time.
Ssh provides an improved version of these types of authentication,
because they are very convenient for the user (and allow easy
transition from rsh and rlogin). It permits these types of
authentication, but additionally requires that the client host be
authenticated using RSA.
The server has a list of host keys stored in /etc/ssh_known_host, and
additionally each user has host keys in $HOME/.ssh/known_hosts. Ssh
uses the name servers to obtain the canonical name of the client host,
looks for its public key in its known host files, and requires the
client to prove that it knows the private host key. This prevents IP
and routing spoofing attacks (as long as the client machine private
host key has not been compromized), but is still vulnerable to DNS
attacks (to a limited extent), and relies on the integrity of the
client machine as to who is requesting to log in. This prevents
outsiders from attacking, but does not protect against very powerful
attackers. If maximal security is desired, only RSA authentication
should be used.
It is possible to enable conventional .rhosts and /etc/hosts.equiv
authentication (without host authentication) at compile time by giving
the option --with-rhosts to configure. However, this is not
recommended, and is not done by default.
These weaknesses are present in rsh and rlogin. No improvement in
security will be obtained unless rlogin and rsh are completely
disabled (commented out in /etc/inetd.conf). This is highly
recommended.
WEAKEST LINKS IN SECURITY
One should understand that while this software may provide
cryptographically secure communications, it may be easy to
monitor the communications at their endpoints.
Basically, anyone with root access on the local machine on which you
are running the software may be able to do anything. Anyone with root
access on the server machine may be able to monitor your
communications, and a very talented root user might even be able to
send his/her own requests to your authentication agent.
One should also be aware that computers send out electromagnetic
radition that can sometimes be picked up hundreds of meters away.
Your keyboard is particularly easy to listen to. The image on your
monitor might also be seen on another monitor in a van parked behind
your house.
Beware that unwanted visitors might come to your home or office and
use your machine while you are away. They might also make
modifications or install bugs in your hardware or software.
Beware that the most effective way for someone to decrypt your data
may be with a rubber hose.
LEGAL ISSUES
As far as I am concerned, anyone is permitted to use this software
freely. However, see the file COPYING for detailed copying,
licensing, and distribution information.
In some countries, particularly France, Russia, Iraq, and Pakistan,
it may be illegal to use any encryption at all without a special
permit, and the rumor has it that you cannot get a permit for any
strong encryption.
This software may be freely imported into the United States; however,
the United States Government may consider re-exporting it a criminal
offence.
Note that any information and cryptographic algorithms used in this
software are publicly available on the Internet and at any major
bookstore, scientific library, or patent office worldwide.
THERE IS NO WARRANTY FOR THIS PROGRAM. Please consult the file
COPYING for more information.
MAILING LISTS AND OTHER INFORMATION
There is a mailing list for ossh. It is ossh@sics.se. If you would
like to join, send a message to majordomo@sics.se with "subscribe
ssh" in body.
The WWW home page for ssh is http://www.cs.hut.fi/ssh. It contains an
archive of the mailing list, and detailed information about new
releases, mailing lists, and other relevant issues.
Bug reports should be sent to ossh-bugs@sics.se.
ABOUT THE AUTHOR
This software was written by Tatu Ylonen <ylo@cs.hut.fi>. I work as a
researcher at Helsinki University of Technology, Finland. For more
information, see http://www.cs.hut.fi/~ylo/. My PGP public key is
available via finger from ylo@cs.hut.fi and from the key servers. I
prefer PGP encrypted mail.
The author can be contacted via ordinary mail at
Tatu Ylonen
Helsinki University of Technology
Otakaari 1
FIN-02150 ESPOO
Finland
Fax. +358-0-4513293
ACKNOWLEDGEMENTS
I thank Tero Kivinen, Timo Rinne, Janne Snabb, and Heikki Suonsivu for
their help and comments in the design, implementation and porting of
this software. I also thank numerous contributors, including but not
limited to Walker Aumann, Jurgen Botz, Hans-Werner Braun, Stephane
Bortzmeyer, Adrian Colley, Michael Cooper, David Dombek, Jerome
Etienne, Bill Fithen, Mark Fullmer, Bert Gijsbers, Andreas Gustafsson,
Michael Henits, Steve Johnson, Thomas Koenig, Felix Leitner, Gunnar
Lindberg, Andrew Macpherson, Marc Martinec, Paul Mauvais, Donald
McKillican, Leon Mlakar, Robert Muchsel, Mark Treacy, Bryan
O'Sullivan, Mikael Suokas, Ollivier Robert, Jakob Schlyter, Tomasz
Surmacz, Alvar Vinacua, Petri Virkkula, Michael Warfield, and
Cristophe Wolfhugel.
Thanks also go to Philip Zimmermann, whose PGP software and the
associated legal battle provided inspiration, motivation, and many
useful techniques, and to Bruce Schneier whose book Applied
Cryptography has done a great service in widely distributing knowledge
about cryptographic methods.
Copyright (c) 1995 Tatu Ylonen, Espoo, Finland.

1780
crypto/dist/ssh/RFC.nroff vendored Normal file

File diff suppressed because it is too large Load Diff

78
crypto/dist/ssh/atomicio.c vendored Normal file
View File

@ -0,0 +1,78 @@
/* $NetBSD: atomicio.c,v 1.1.1.1 2000/09/28 22:09:38 thorpej Exp $ */
/*
* Copyright (c) 1995,1999 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.
*/
/* from OpenBSD: atomicio.c,v 1.5 2000/09/07 20:27:49 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: atomicio.c,v 1.1.1.1 2000/09/28 22:09:38 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
ssize_t
atomic_read(int fd, void *v, size_t n)
{
char *s = v;
ssize_t res, pos = 0;
while (n > pos) {
res = read(fd, s + pos, n - pos);
switch (res) {
case -1:
if (errno == EINTR || errno == EAGAIN)
continue;
case 0:
return (res);
default:
pos += res;
}
}
return (pos);
}
ssize_t
atomic_write(int fd, const void *v, size_t n)
{
const char *s = v;
ssize_t res, pos = 0;
while (n > pos) {
res = write(fd, s + pos, n - pos);
switch (res) {
case -1:
if (errno == EINTR || errno == EAGAIN)
continue;
case 0:
return (res);
default:
pos += res;
}
}
return (pos);
}

379
crypto/dist/ssh/auth-krb4.c vendored Normal file
View File

@ -0,0 +1,379 @@
/* $NetBSD: auth-krb4.c,v 1.1.1.1 2000/09/28 22:09:38 thorpej Exp $ */
/*
* Copyright (c) 1999 Dug Song. 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.
*/
/* from: OpenBSD: auth-krb4.c,v 1.18 2000/09/07 20:27:49 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: auth-krb4.c,v 1.1.1.1 2000/09/28 22:09:38 thorpej Exp $");
#endif
#include "includes.h"
#include "packet.h"
#include "xmalloc.h"
#include "ssh.h"
#include "servconf.h"
#ifdef KRB4
char *ticket = NULL;
extern ServerOptions options;
/*
* try krb4 authentication,
* return 1 on success, 0 on failure, -1 if krb4 is not available
*/
int
auth_krb4_password(struct passwd * pw, const char *password)
{
AUTH_DAT adata;
KTEXT_ST tkt;
struct hostent *hp;
unsigned long faddr;
char localhost[MAXHOSTNAMELEN];
char phost[INST_SZ];
char realm[REALM_SZ];
int r;
/*
* Try Kerberos password authentication only for non-root
* users and only if Kerberos is installed.
*/
if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) {
/* Set up our ticket file. */
if (!krb4_init(pw->pw_uid)) {
log("Couldn't initialize Kerberos ticket file for %s!",
pw->pw_name);
goto kerberos_auth_failure;
}
/* Try to get TGT using our password. */
r = krb_get_pw_in_tkt((char *) pw->pw_name, "",
realm, "krbtgt", realm,
DEFAULT_TKT_LIFE, (char *) password);
if (r != INTK_OK) {
packet_send_debug("Kerberos V4 password "
"authentication for %s failed: %s",
pw->pw_name, krb_err_txt[r]);
goto kerberos_auth_failure;
}
/* Successful authentication. */
chown(tkt_string(), pw->pw_uid, pw->pw_gid);
/*
* Now that we have a TGT, try to get a local
* "rcmd" ticket to ensure that we are not talking
* to a bogus Kerberos server.
*/
(void) gethostname(localhost, sizeof(localhost));
(void) strlcpy(phost, (char *) krb_get_phost(localhost),
INST_SZ);
r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33);
if (r == KSUCCESS) {
if (!(hp = gethostbyname(localhost))) {
log("Couldn't get local host address!");
goto kerberos_auth_failure;
}
memmove((void *) &faddr, (void *) hp->h_addr,
sizeof(faddr));
/* Verify our "rcmd" ticket. */
r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost,
faddr, &adata, "");
if (r == RD_AP_UNDEC) {
/*
* Probably didn't have a srvtab on
* localhost. Disallow login.
*/
log("Kerberos V4 TGT for %s unverifiable, "
"no srvtab installed? krb_rd_req: %s",
pw->pw_name, krb_err_txt[r]);
goto kerberos_auth_failure;
} else if (r != KSUCCESS) {
log("Kerberos V4 %s ticket unverifiable: %s",
KRB4_SERVICE_NAME, krb_err_txt[r]);
goto kerberos_auth_failure;
}
} else if (r == KDC_PR_UNKNOWN) {
/*
* Disallow login if no rcmd service exists, and
* log the error.
*/
log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
"not registered, or srvtab is wrong?", pw->pw_name,
krb_err_txt[r], KRB4_SERVICE_NAME, phost);
goto kerberos_auth_failure;
} else {
/*
* TGT is bad, forget it. Possibly spoofed!
*/
packet_send_debug("WARNING: Kerberos V4 TGT "
"possibly spoofed for %s: %s",
pw->pw_name, krb_err_txt[r]);
goto kerberos_auth_failure;
}
/* Authentication succeeded. */
return 1;
kerberos_auth_failure:
krb4_cleanup_proc(NULL);
if (!options.kerberos_or_local_passwd)
return 0;
} else {
/* Logging in as root or no local Kerberos realm. */
packet_send_debug("Unable to authenticate to Kerberos.");
}
/* Fall back to ordinary passwd authentication. */
return -1;
}
void
krb4_cleanup_proc(void *ignore)
{
debug("krb4_cleanup_proc called");
if (ticket) {
(void) dest_tkt();
xfree(ticket);
ticket = NULL;
}
}
int
krb4_init(uid_t uid)
{
static int cleanup_registered = 0;
const char *tkt_root = TKT_ROOT;
struct stat st;
int fd;
if (!ticket) {
/* Set unique ticket string manually since we're still root. */
ticket = xmalloc(MAXPATHLEN);
#ifdef AFS
if (lstat("/ticket", &st) != -1)
tkt_root = "/ticket/";
#endif /* AFS */
snprintf(ticket, MAXPATHLEN, "%s%u_%d", tkt_root, uid, getpid());
(void) krb_set_tkt_string(ticket);
}
/* Register ticket cleanup in case of fatal error. */
if (!cleanup_registered) {
fatal_add_cleanup(krb4_cleanup_proc, NULL);
cleanup_registered = 1;
}
/* Try to create our ticket file. */
if ((fd = mkstemp(ticket)) != -1) {
close(fd);
return 1;
}
/* Ticket file exists - make sure user owns it (just passed ticket). */
if (lstat(ticket, &st) != -1) {
if (st.st_mode == (S_IFREG | S_IRUSR | S_IWUSR) &&
st.st_uid == uid)
return 1;
}
/* Failure - cancel cleanup function, leaving bad ticket for inspection. */
log("WARNING: bad ticket file %s", ticket);
fatal_remove_cleanup(krb4_cleanup_proc, NULL);
cleanup_registered = 0;
xfree(ticket);
ticket = NULL;
return 0;
}
int
auth_krb4(const char *server_user, KTEXT auth, char **client)
{
AUTH_DAT adat = {0};
KTEXT_ST reply;
char instance[INST_SZ];
int r, s;
socklen_t slen;
u_int cksum;
Key_schedule schedule;
struct sockaddr_in local, foreign;
s = packet_get_connection_in();
slen = sizeof(local);
memset(&local, 0, sizeof(local));
if (getsockname(s, (struct sockaddr *) & local, &slen) < 0)
debug("getsockname failed: %.100s", strerror(errno));
slen = sizeof(foreign);
memset(&foreign, 0, sizeof(foreign));
if (getpeername(s, (struct sockaddr *) & foreign, &slen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
instance[0] = '*';
instance[1] = 0;
/* Get the encrypted request, challenge, and session key. */
if ((r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, 0, &adat, ""))) {
packet_send_debug("Kerberos V4 krb_rd_req: %.100s", krb_err_txt[r]);
return 0;
}
des_key_sched((des_cblock *) adat.session, schedule);
*client = xmalloc(MAX_K_NAME_SZ);
(void) snprintf(*client, MAX_K_NAME_SZ, "%s%s%s@%s", adat.pname,
*adat.pinst ? "." : "", adat.pinst, adat.prealm);
/* Check ~/.klogin authorization now. */
if (kuserok(&adat, (char *) server_user) != KSUCCESS) {
packet_send_debug("Kerberos V4 .klogin authorization failed!");
log("Kerberos V4 .klogin authorization failed for %s to account %s",
*client, server_user);
xfree(*client);
return 0;
}
/* Increment the checksum, and return it encrypted with the
session key. */
cksum = adat.checksum + 1;
cksum = htonl(cksum);
/* If we can't successfully encrypt the checksum, we send back an
empty message, admitting our failure. */
if ((r = krb_mk_priv((u_char *) & cksum, reply.dat, sizeof(cksum) + 1,
schedule, &adat.session, &local, &foreign)) < 0) {
packet_send_debug("Kerberos V4 mk_priv: (%d) %s", r, krb_err_txt[r]);
reply.dat[0] = 0;
reply.length = 0;
} else
reply.length = r;
/* Clear session key. */
memset(&adat.session, 0, sizeof(&adat.session));
packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
packet_put_string((char *) reply.dat, reply.length);
packet_send();
packet_write_wait();
return 1;
}
#endif /* KRB4 */
#ifdef AFS
int
auth_kerberos_tgt(struct passwd *pw, const char *string)
{
CREDENTIALS creds;
if (!radix_to_creds(string, &creds)) {
log("Protocol error decoding Kerberos V4 tgt");
packet_send_debug("Protocol error decoding Kerberos V4 tgt");
goto auth_kerberos_tgt_failure;
}
if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
strlcpy(creds.service, "krbtgt", sizeof creds.service);
if (strcmp(creds.service, "krbtgt")) {
log("Kerberos V4 tgt (%s%s%s@%s) rejected for %s", creds.pname,
creds.pinst[0] ? "." : "", creds.pinst, creds.realm,
pw->pw_name);
packet_send_debug("Kerberos V4 tgt (%s%s%s@%s) rejected for %s",
creds.pname, creds.pinst[0] ? "." : "", creds.pinst,
creds.realm, pw->pw_name);
goto auth_kerberos_tgt_failure;
}
if (!krb4_init(pw->pw_uid))
goto auth_kerberos_tgt_failure;
if (in_tkt(creds.pname, creds.pinst) != KSUCCESS)
goto auth_kerberos_tgt_failure;
if (save_credentials(creds.service, creds.instance, creds.realm,
creds.session, creds.lifetime, creds.kvno,
&creds.ticket_st, creds.issue_date) != KSUCCESS) {
packet_send_debug("Kerberos V4 tgt refused: couldn't save credentials");
goto auth_kerberos_tgt_failure;
}
/* Successful authentication, passed all checks. */
chown(tkt_string(), pw->pw_uid, pw->pw_gid);
packet_send_debug("Kerberos V4 tgt accepted (%s.%s@%s, %s%s%s@%s)",
creds.service, creds.instance, creds.realm, creds.pname,
creds.pinst[0] ? "." : "", creds.pinst, creds.realm);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
return 1;
auth_kerberos_tgt_failure:
krb4_cleanup_proc(NULL);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
return 0;
}
int
auth_afs_token(struct passwd *pw, const char *token_string)
{
CREDENTIALS creds;
uid_t uid = pw->pw_uid;
if (!radix_to_creds(token_string, &creds)) {
log("Protocol error decoding AFS token");
packet_send_debug("Protocol error decoding AFS token");
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
return 0;
}
if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
strlcpy(creds.service, "afs", sizeof creds.service);
if (strncmp(creds.pname, "AFS ID ", 7) == 0)
uid = atoi(creds.pname + 7);
if (kafs_settoken(creds.realm, uid, &creds)) {
log("AFS token (%s@%s) rejected for %s", creds.pname, creds.realm,
pw->pw_name);
packet_send_debug("AFS token (%s@%s) rejected for %s", creds.pname,
creds.realm, pw->pw_name);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
return 0;
}
packet_send_debug("AFS token accepted (%s@%s, %s@%s)", creds.service,
creds.realm, creds.pname, creds.realm);
memset(&creds, 0, sizeof(creds));
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
return 1;
}
#endif /* AFS */

233
crypto/dist/ssh/auth-options.c vendored Normal file
View File

@ -0,0 +1,233 @@
/* $NetBSD: auth-options.c,v 1.1.1.1 2000/09/28 22:09:39 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* RSA-based authentication. This code determines whether to admit a login
* based on RSA authentication. This file also contains functions to check
* validity of the host key.
*
* 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".
*/
/* from OpenBSD: auth-options.c,v 1.4 2000/09/07 21:13:36 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: auth-options.c,v 1.1.1.1 2000/09/28 22:09:39 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "packet.h"
#include "pathnames.h"
#include "xmalloc.h"
#include "match.h"
#include "auth-options.h"
/* Flags set authorized_keys flags */
int no_port_forwarding_flag = 0;
int no_agent_forwarding_flag = 0;
int no_x11_forwarding_flag = 0;
int no_pty_flag = 0;
/* "command=" option. */
char *forced_command = NULL;
/* "environment=" options. */
struct envstring *custom_environment = NULL;
/* return 1 if access is granted, 0 if not. side effect: sets key option flags */
int
auth_parse_options(struct passwd *pw, char *options, unsigned long linenum)
{
const char *cp;
if (!options)
return 1;
while (*options && *options != ' ' && *options != '\t') {
cp = "no-port-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("Port forwarding disabled.");
no_port_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-agent-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("Agent forwarding disabled.");
no_agent_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-X11-forwarding";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("X11 forwarding disabled.");
no_x11_forwarding_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "no-pty";
if (strncmp(options, cp, strlen(cp)) == 0) {
packet_send_debug("Pty allocation disabled.");
no_pty_flag = 1;
options += strlen(cp);
goto next_option;
}
cp = "command=\"";
if (strncmp(options, cp, strlen(cp)) == 0) {
int i;
options += strlen(cp);
forced_command = xmalloc(strlen(options) + 1);
i = 0;
while (*options) {
if (*options == '"')
break;
if (*options == '\\' && options[1] == '"') {
options += 2;
forced_command[i++] = '"';
continue;
}
forced_command[i++] = *options++;
}
if (!*options) {
debug("%.100s, line %lu: missing end quote",
_PATH_SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
_PATH_SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
forced_command[i] = 0;
packet_send_debug("Forced command: %.900s", forced_command);
options++;
goto next_option;
}
cp = "environment=\"";
if (strncmp(options, cp, strlen(cp)) == 0) {
int i;
char *s;
struct envstring *new_envstring;
options += strlen(cp);
s = xmalloc(strlen(options) + 1);
i = 0;
while (*options) {
if (*options == '"')
break;
if (*options == '\\' && options[1] == '"') {
options += 2;
s[i++] = '"';
continue;
}
s[i++] = *options++;
}
if (!*options) {
debug("%.100s, line %lu: missing end quote",
_PATH_SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
_PATH_SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
s[i] = 0;
packet_send_debug("Adding to environment: %.900s", s);
debug("Adding to environment: %.900s", s);
options++;
new_envstring = xmalloc(sizeof(struct envstring));
new_envstring->s = s;
new_envstring->next = custom_environment;
custom_environment = new_envstring;
goto next_option;
}
cp = "from=\"";
if (strncmp(options, cp, strlen(cp)) == 0) {
int mname, mip;
char *patterns = xmalloc(strlen(options) + 1);
int i;
options += strlen(cp);
i = 0;
while (*options) {
if (*options == '"')
break;
if (*options == '\\' && options[1] == '"') {
options += 2;
patterns[i++] = '"';
continue;
}
patterns[i++] = *options++;
}
if (!*options) {
debug("%.100s, line %lu: missing end quote",
_PATH_SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: missing end quote",
_PATH_SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
patterns[i] = 0;
options++;
/*
* Deny access if we get a negative
* match for the hostname or the ip
* or if we get not match at all
*/
mname = match_hostname(get_canonical_hostname(),
patterns, strlen(patterns));
mip = match_hostname(get_remote_ipaddr(),
patterns, strlen(patterns));
xfree(patterns);
if (mname == -1 || mip == -1 ||
(mname != 1 && mip != 1)) {
log("Authentication tried for %.100s with correct key but not from a permitted host (host=%.200s, ip=%.200s).",
pw->pw_name, get_canonical_hostname(),
get_remote_ipaddr());
packet_send_debug("Your host '%.200s' is not permitted to use this key for login.",
get_canonical_hostname());
/* key invalid for this host, reset flags */
no_agent_forwarding_flag = 0;
no_port_forwarding_flag = 0;
no_pty_flag = 0;
no_x11_forwarding_flag = 0;
while (custom_environment) {
struct envstring *ce = custom_environment;
custom_environment = ce->next;
xfree(ce->s);
xfree(ce);
}
if (forced_command) {
xfree(forced_command);
forced_command = NULL;
}
/* deny access */
return 0;
}
/* Host name matches. */
goto next_option;
}
next_option:
/*
* Skip the comma, and move to the next option
* (or break out if there are no more).
*/
if (!*options)
fatal("Bugs in auth-options.c option processing.");
if (*options == ' ' || *options == '\t')
break; /* End of options. */
if (*options != ',')
goto bad_option;
options++;
/* Process the next option. */
}
/* grant access */
return 1;
bad_option:
log("Bad options in %.100s file, line %lu: %.50s",
_PATH_SSH_USER_PERMITTED_KEYS, linenum, options);
packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
_PATH_SSH_USER_PERMITTED_KEYS, linenum, options);
/* deny access */
return 0;
}

28
crypto/dist/ssh/auth-options.h vendored Normal file
View File

@ -0,0 +1,28 @@
/* $NetBSD: auth-options.h,v 1.1.1.1 2000/09/28 22:09:39 thorpej 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 AUTH_OPTIONS_H
#define AUTH_OPTIONS_H
/* Flags that may be set in authorized_keys options. */
extern int no_port_forwarding_flag;
extern int no_agent_forwarding_flag;
extern int no_x11_forwarding_flag;
extern int no_pty_flag;
extern char *forced_command;
extern struct envstring *custom_environment;
/* return 1 if access is granted, 0 if not. side effect: sets key option flags */
int auth_parse_options(struct passwd *pw, char *options, unsigned long linenum);
#endif

136
crypto/dist/ssh/auth-passwd.c vendored Normal file
View File

@ -0,0 +1,136 @@
/* $NetBSD: auth-passwd.c,v 1.1.1.1 2000/09/28 22:09:39 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Password authentication. This file contains the functions to check whether
* the password is valid for the user.
*
* 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) 1999 Dug Song. 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.
*
*
* 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.
*/
/* from OpenBSD: auth-passwd.c,v 1.17 2000/09/07 20:27:49 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: auth-passwd.c,v 1.1.1.1 2000/09/28 22:09:39 thorpej Exp $");
#endif
#include "includes.h"
#include "packet.h"
#include "ssh.h"
#include "servconf.h"
#include "xmalloc.h"
/*
* Tries to authenticate the user using password. Returns true if
* authentication succeeds.
*/
int
auth_password(struct passwd * pw, const char *password)
{
extern ServerOptions options;
char *encrypted_password;
/* deny if no user. */
if (pw == NULL)
return 0;
if (pw->pw_uid == 0 && options.permit_root_login == 2)
return 0;
if (*password == '\0' && options.permit_empty_passwd == 0)
return 0;
#ifdef SKEY
if (options.skey_authentication == 1) {
int ret = auth_skey_password(pw, password);
if (ret == 1 || ret == 0)
return ret;
/* Fall back to ordinary passwd authentication. */
}
#endif
#if defined(KRB4) || defined(KRB5)
{
int ret;
switch (options.kerberos_authentication) {
#ifdef KRBB4
case 4:
ret = auth_krb4_password(pw, password);
break;
#endif
#ifdef KRB5
case 5:
ret = auth_krb5_password(pw, password);
break;
#endif
default:
ret = -1;
}
if (ret == 1 || ret == 0)
return ret;
}
/* Fall back to ordinary passwd authentication. */
#endif /* KRB4 || KRB5 */
/* Check for users with no password. */
if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0)
return 1;
/* Encrypt the candidate password using the proper salt. */
encrypted_password = crypt(password,
(pw->pw_passwd[0] && pw->pw_passwd[1]) ? pw->pw_passwd : "xx");
/* Authentication is accepted if the encrypted passwords are identical. */
return (strcmp(encrypted_password, pw->pw_passwd) == 0);
}

122
crypto/dist/ssh/auth-rh-rsa.c vendored Normal file
View File

@ -0,0 +1,122 @@
/* $NetBSD: auth-rh-rsa.c,v 1.1.1.1 2000/09/28 22:09:39 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Rhosts or /etc/hosts.equiv authentication combined with RSA host
* authentication.
*
* 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".
*/
/* from OpenBSD: auth-rh-rsa.c,v 1.16 2000/09/07 21:13:36 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: auth-rh-rsa.c,v 1.1.1.1 2000/09/28 22:09:39 thorpej Exp $");
#endif
#include "includes.h"
#include "packet.h"
#include "pathnames.h"
#include "ssh.h"
#include "xmalloc.h"
#include "uidswap.h"
#include "servconf.h"
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include "key.h"
#include "hostfile.h"
/*
* Tries to authenticate the user using the .rhosts file and the host using
* its host key. Returns true if authentication succeeds.
*/
int
auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key)
{
extern ServerOptions options;
const char *canonical_hostname;
HostStatus host_status;
Key *client_key, *found;
debug("Trying rhosts with RSA host authentication for %.100s", client_user);
if (client_host_key == NULL)
return 0;
/* Check if we would accept it using rhosts authentication. */
if (!auth_rhosts(pw, client_user))
return 0;
canonical_hostname = get_canonical_hostname();
debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname);
/* wrap the RSA key into a 'generic' key */
client_key = key_new(KEY_RSA);
BN_copy(client_key->rsa->e, client_host_key->e);
BN_copy(client_key->rsa->n, client_host_key->n);
found = key_new(KEY_RSA);
/* Check if we know the host and its host key. */
host_status = check_host_in_hostfile(_PATH_SSH_SYSTEM_HOSTFILE, canonical_hostname,
client_key, found);
/* Check user host file unless ignored. */
if (host_status != HOST_OK && !options.ignore_user_known_hosts) {
struct stat st;
char *user_hostfile = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
/*
* Check file permissions of _PATH_SSH_USER_HOSTFILE, auth_rsa()
* did already check pw->pw_dir, but there is a race XXX
*/
if (options.strict_modes &&
(stat(user_hostfile, &st) == 0) &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
log("Rhosts RSA authentication refused for %.100s: bad owner or modes for %.200s",
pw->pw_name, user_hostfile);
} else {
/* XXX race between stat and the following open() */
temporarily_use_uid(pw->pw_uid);
host_status = check_host_in_hostfile(user_hostfile, canonical_hostname,
client_key, found);
restore_uid();
}
xfree(user_hostfile);
}
key_free(client_key);
key_free(found);
if (host_status != HOST_OK) {
debug("Rhosts with RSA host authentication denied: unknown or invalid host key");
packet_send_debug("Your host key cannot be verified: unknown or invalid host key.");
return 0;
}
/* A matching host key was found and is known. */
/* Perform the challenge-response dialog with the client for the host key. */
if (!auth_rsa_challenge_dialog(client_host_key)) {
log("Client on %.800s failed to respond correctly to host authentication.",
canonical_hostname);
return 0;
}
/*
* We have authenticated the user using .rhosts or /etc/hosts.equiv,
* and the host using RSA. We accept the authentication.
*/
verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.",
pw->pw_name, client_user, canonical_hostname);
packet_send_debug("Rhosts with RSA host authentication accepted.");
return 1;
}

273
crypto/dist/ssh/auth-rhosts.c vendored Normal file
View File

@ -0,0 +1,273 @@
/* $NetBSD: auth-rhosts.c,v 1.1.1.1 2000/09/28 22:09:40 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Rhosts authentication. This file contains code to check whether to admit
* the login based on rhosts authentication. This file also processes
* /etc/hosts.equiv.
*
* 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".
*/
/* from OpenBSD: auth-rhosts.c,v 1.15 2000/09/07 20:27:49 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: auth-rhosts.c,v 1.1.1.1 2000/09/28 22:09:40 thorpej Exp $");
#endif
#include "includes.h"
#include "packet.h"
#include "pathnames.h"
#include "ssh.h"
#include "xmalloc.h"
#include "uidswap.h"
#include "servconf.h"
/*
* This function processes an rhosts-style file (.rhosts, .shosts, or
* /etc/hosts.equiv). This returns true if authentication can be granted
* based on the file, and returns zero otherwise.
*/
static int
check_rhosts_file(const char *filename, const char *hostname,
const char *ipaddr, const char *client_user,
const char *server_user)
{
FILE *f;
char buf[1024]; /* Must not be larger than host, user, dummy below. */
/* Open the .rhosts file, deny if unreadable */
f = fopen(filename, "r");
if (!f)
return 0;
while (fgets(buf, sizeof(buf), f)) {
/* All three must be at least as big as buf to avoid overflows. */
char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp;
int negated;
for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
;
if (*cp == '#' || *cp == '\n' || !*cp)
continue;
/*
* NO_PLUS is supported at least on OSF/1. We skip it (we
* don't ever support the plus syntax).
*/
if (strncmp(cp, "NO_PLUS", 7) == 0)
continue;
/*
* This should be safe because each buffer is as big as the
* whole string, and thus cannot be overwritten.
*/
switch (sscanf(buf, "%s %s %s", hostbuf, userbuf, dummy)) {
case 0:
packet_send_debug("Found empty line in %.100s.", filename);
continue;
case 1:
/* Host name only. */
strlcpy(userbuf, server_user, sizeof(userbuf));
break;
case 2:
/* Got both host and user name. */
break;
case 3:
packet_send_debug("Found garbage in %.100s.", filename);
continue;
default:
/* Weird... */
continue;
}
host = hostbuf;
user = userbuf;
negated = 0;
/* Process negated host names, or positive netgroups. */
if (host[0] == '-') {
negated = 1;
host++;
} else if (host[0] == '+')
host++;
if (user[0] == '-') {
negated = 1;
user++;
} else if (user[0] == '+')
user++;
/* Check for empty host/user names (particularly '+'). */
if (!host[0] || !user[0]) {
/* We come here if either was '+' or '-'. */
packet_send_debug("Ignoring wild host/user names in %.100s.",
filename);
continue;
}
/* Verify that host name matches. */
if (host[0] == '@') {
if (!innetgr(host + 1, hostname, NULL, NULL) &&
!innetgr(host + 1, ipaddr, NULL, NULL))
continue;
} else if (strcasecmp(host, hostname) && strcmp(host, ipaddr) != 0)
continue; /* Different hostname. */
/* Verify that user name matches. */
if (user[0] == '@') {
if (!innetgr(user + 1, NULL, client_user, NULL))
continue;
} else if (strcmp(user, client_user) != 0)
continue; /* Different username. */
/* Found the user and host. */
fclose(f);
/* If the entry was negated, deny access. */
if (negated) {
packet_send_debug("Matched negative entry in %.100s.",
filename);
return 0;
}
/* Accept authentication. */
return 1;
}
/* Authentication using this file denied. */
fclose(f);
return 0;
}
/*
* Tries to authenticate the user using the .shosts or .rhosts file. Returns
* true if authentication succeeds. If ignore_rhosts is true, only
* /etc/hosts.equiv will be considered (.rhosts and .shosts are ignored).
*/
int
auth_rhosts(struct passwd *pw, const char *client_user)
{
extern ServerOptions options;
char buf[1024];
const char *hostname, *ipaddr;
struct stat st;
static const char *rhosts_files[] = {".shosts", ".rhosts", NULL};
unsigned int rhosts_file_index;
/* Switch to the user's uid. */
temporarily_use_uid(pw->pw_uid);
/*
* Quick check: if the user has no .shosts or .rhosts files, return
* failure immediately without doing costly lookups from name
* servers.
*/
for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
rhosts_file_index++) {
/* Check users .rhosts or .shosts. */
snprintf(buf, sizeof buf, "%.500s/%.100s",
pw->pw_dir, rhosts_files[rhosts_file_index]);
if (stat(buf, &st) >= 0)
break;
}
/* Switch back to privileged uid. */
restore_uid();
/* Deny if The user has no .shosts or .rhosts file and there are no system-wide files. */
if (!rhosts_files[rhosts_file_index] &&
stat(_PATH_HEQUIV, &st) < 0 &&
stat(_PATH_SSH_HEQUIV, &st) < 0)
return 0;
hostname = get_canonical_hostname();
ipaddr = get_remote_ipaddr();
/* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
if (pw->pw_uid != 0) {
if (check_rhosts_file(_PATH_HEQUIV, hostname, ipaddr, client_user,
pw->pw_name)) {
packet_send_debug("Accepted for %.100s [%.100s] by " _PATH_HEQUIV ".",
hostname, ipaddr);
return 1;
}
if (check_rhosts_file(_PATH_SSH_HEQUIV, hostname, ipaddr, client_user,
pw->pw_name)) {
packet_send_debug("Accepted for %.100s [%.100s] by %.100s.",
hostname, ipaddr, _PATH_SSH_HEQUIV);
return 1;
}
}
/*
* Check that the home directory is owned by root or the user, and is
* not group or world writable.
*/
if (stat(pw->pw_dir, &st) < 0) {
log("Rhosts authentication refused for %.100s: no home directory %.200s",
pw->pw_name, pw->pw_dir);
packet_send_debug("Rhosts authentication refused for %.100s: no home directory %.200s",
pw->pw_name, pw->pw_dir);
return 0;
}
if (options.strict_modes &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
log("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
pw->pw_name);
packet_send_debug("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
pw->pw_name);
return 0;
}
/* Temporarily use the user's uid. */
temporarily_use_uid(pw->pw_uid);
/* Check all .rhosts files (currently .shosts and .rhosts). */
for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
rhosts_file_index++) {
/* Check users .rhosts or .shosts. */
snprintf(buf, sizeof buf, "%.500s/%.100s",
pw->pw_dir, rhosts_files[rhosts_file_index]);
if (stat(buf, &st) < 0)
continue;
/*
* Make sure that the file is either owned by the user or by
* root, and make sure it is not writable by anyone but the
* owner. This is to help avoid novices accidentally
* allowing access to their account by anyone.
*/
if (options.strict_modes &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
log("Rhosts authentication refused for %.100s: bad modes for %.200s",
pw->pw_name, buf);
packet_send_debug("Bad file modes for %.200s", buf);
continue;
}
/* Check if we have been configured to ignore .rhosts and .shosts files. */
if (options.ignore_rhosts) {
packet_send_debug("Server has been configured to ignore %.100s.",
rhosts_files[rhosts_file_index]);
continue;
}
/* Check if authentication is permitted by the file. */
if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name)) {
packet_send_debug("Accepted by %.100s.",
rhosts_files[rhosts_file_index]);
/* Restore the privileged uid. */
restore_uid();
return 1;
}
}
/* Restore the privileged uid. */
restore_uid();
return 0;
}

292
crypto/dist/ssh/auth-rsa.c vendored Normal file
View File

@ -0,0 +1,292 @@
/* $NetBSD: auth-rsa.c,v 1.1.1.1 2000/09/28 22:09:40 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* RSA-based authentication. This code determines whether to admit a login
* based on RSA authentication. This file also contains functions to check
* validity of the host key.
*
* 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".
*/
/* from OpenBSD: auth-rsa.c,v 1.29 2000/09/07 21:13:36 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: auth-rsa.c,v 1.1.1.1 2000/09/28 22:09:40 thorpej Exp $");
#endif
#include "includes.h"
#include "rsa.h"
#include "packet.h"
#include "pathnames.h"
#include "xmalloc.h"
#include "ssh.h"
#include "mpaux.h"
#include "uidswap.h"
#include "match.h"
#include "servconf.h"
#include "auth-options.h"
#include <openssl/rsa.h>
#include <openssl/md5.h>
/*
* Session identifier that is used to bind key exchange and authentication
* responses to a particular session.
*/
extern unsigned char session_id[16];
/*
* The .ssh/authorized_keys file contains public keys, one per line, in the
* following format:
* options bits e n comment
* where bits, e and n are decimal numbers,
* and comment is any string of characters up to newline. The maximum
* length of a line is 8000 characters. See the documentation for a
* description of the options.
*/
/*
* Performs the RSA authentication challenge-response dialog with the client,
* and returns true (non-zero) if the client gave the correct answer to
* our challenge; returns zero if the client gives a wrong answer.
*/
int
auth_rsa_challenge_dialog(RSA *pk)
{
BIGNUM *challenge, *encrypted_challenge;
BN_CTX *ctx;
unsigned char buf[32], mdbuf[16], response[16];
MD5_CTX md;
unsigned int i;
int plen, len;
encrypted_challenge = BN_new();
challenge = BN_new();
/* Generate a random challenge. */
BN_rand(challenge, 256, 0, 0);
ctx = BN_CTX_new();
BN_mod(challenge, challenge, pk->n, ctx);
BN_CTX_free(ctx);
/* Encrypt the challenge with the public key. */
rsa_public_encrypt(encrypted_challenge, challenge, pk);
/* Send the encrypted challenge to the client. */
packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
packet_put_bignum(encrypted_challenge);
packet_send();
BN_clear_free(encrypted_challenge);
packet_write_wait();
/* Wait for a response. */
packet_read_expect(&plen, SSH_CMSG_AUTH_RSA_RESPONSE);
packet_integrity_check(plen, 16, SSH_CMSG_AUTH_RSA_RESPONSE);
for (i = 0; i < 16; i++)
response[i] = packet_get_char();
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32)
fatal("auth_rsa_challenge_dialog: bad challenge length %d", len);
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
BN_clear_free(challenge);
/* Verify that the response is the original challenge. */
if (memcmp(response, mdbuf, 16) != 0) {
/* Wrong answer. */
return 0;
}
/* Correct answer. */
return 1;
}
/*
* Performs the RSA authentication dialog with the client. This returns
* 0 if the client could not be authenticated, and 1 if authentication was
* successful. This may exit if there is a serious protocol violation.
*/
int
auth_rsa(struct passwd *pw, BIGNUM *client_n)
{
extern ServerOptions options;
char line[8192], file[1024];
int authenticated;
unsigned int bits;
FILE *f;
unsigned long linenum = 0;
struct stat st;
RSA *pk;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw->pw_uid);
/* The authorized keys. */
snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
_PATH_SSH_USER_PERMITTED_KEYS);
/* Fail quietly if file does not exist */
if (stat(file, &st) < 0) {
/* Restore the privileged uid. */
restore_uid();
return 0;
}
/* Open the file containing the authorized keys. */
f = fopen(file, "r");
if (!f) {
/* Restore the privileged uid. */
restore_uid();
packet_send_debug("Could not open %.900s for reading.", file);
packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
return 0;
}
if (options.strict_modes) {
int fail = 0;
char buf[1024];
/* Check open file in order to avoid open/stat races */
if (fstat(fileno(f), &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
"bad ownership or modes for '%s'.", pw->pw_name, file);
fail = 1;
} else {
/* Check path to _PATH_SSH_USER_PERMITTED_KEYS */
int i;
static const char *check[] = {
"", _PATH_SSH_USER_DIR, NULL
};
for (i = 0; check[i]; i++) {
snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]);
if (stat(line, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf, "RSA authentication refused for %.100s: "
"bad ownership or modes for '%s'.", pw->pw_name, line);
fail = 1;
break;
}
}
}
if (fail) {
fclose(f);
log("%s",buf);
packet_send_debug("%s",buf);
restore_uid();
return 0;
}
}
/* Flag indicating whether authentication has succeeded. */
authenticated = 0;
pk = RSA_new();
pk->e = BN_new();
pk->n = BN_new();
/*
* Go though the accepted keys, looking for the current key. If
* found, perform a challenge-response dialog to verify that the
* user really has the corresponding private key.
*/
while (fgets(line, sizeof(line), f)) {
char *cp;
char *options;
linenum++;
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '\n' || *cp == '#')
continue;
/*
* Check if there are options for this key, and if so,
* save their starting address and skip the option part
* for now. If there are no options, set the starting
* address to NULL.
*/
if (*cp < '0' || *cp > '9') {
int quoted = 0;
options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
} else
options = NULL;
/* Parse the key from the line. */
if (!auth_rsa_read_key(&cp, &bits, pk->e, pk->n)) {
debug("%.100s, line %lu: bad key syntax",
_PATH_SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: bad key syntax",
_PATH_SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
/* cp now points to the comment part. */
/* Check if the we have found the desired key (identified by its modulus). */
if (BN_cmp(pk->n, client_n) != 0)
continue;
/* check the real bits */
if (bits != BN_num_bits(pk->n))
log("Warning: %s, line %ld: keysize mismatch: "
"actual %d vs. announced %d.",
file, linenum, BN_num_bits(pk->n), bits);
/* We have found the desired key. */
/* Perform the challenge-response dialog for this key. */
if (!auth_rsa_challenge_dialog(pk)) {
/* Wrong response. */
verbose("Wrong response to RSA authentication challenge.");
packet_send_debug("Wrong response to RSA authentication challenge.");
continue;
}
/*
* Correct response. The client has been successfully
* authenticated. Note that we have not yet processed the
* options; this will be reset if the options cause the
* authentication to be rejected.
* Break out of the loop if authentication was successful;
* otherwise continue searching.
*/
authenticated = auth_parse_options(pw, options, linenum);
if (authenticated)
break;
}
/* Restore the privileged uid. */
restore_uid();
/* Close the file. */
fclose(f);
RSA_free(pk);
if (authenticated)
packet_send_debug("RSA authentication accepted.");
/* Return authentication result. */
return authenticated;
}

214
crypto/dist/ssh/auth-skey.c vendored Normal file
View File

@ -0,0 +1,214 @@
/* $NetBSD: auth-skey.c,v 1.1.1.1 2000/09/28 22:09:41 thorpej Exp $ */
/*
* Copyright (c) 1999,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.
*/
/* from OpenBSD: auth-skey.c,v 1.8 2000/09/07 20:27:49 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: auth-skey.c,v 1.1.1.1 2000/09/28 22:09:41 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "packet.h"
#include <sha1.h>
/*
* try skey authentication,
* return 1 on success, 0 on failure, -1 if skey is not available
*/
int
auth_skey_password(struct passwd * pw, const char *password)
{
if (strncasecmp(password, "s/key", 5) == 0) {
const char *skeyinfo = skey_keyinfo(pw->pw_name);
if (skeyinfo == NULL) {
debug("generating fake skeyinfo for %.100s.",
pw->pw_name);
skeyinfo = skey_fake_keyinfo(pw->pw_name);
}
if (skeyinfo != NULL)
packet_send_debug(skeyinfo);
/* Try again. */
return 0;
} else if (skey_haskey(pw->pw_name) == 0 &&
skey_passcheck(pw->pw_name, (char *) password) != -1) {
/* Authentication succeeded. */
return 1;
}
/* Fall back to ordinary passwd authentication. */
return -1;
}
/* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
#define ROUND(x) (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
((x)[3]))
/*
* hash_collapse()
*/
static u_int32_t
hash_collapse(u_char *s)
{
int len, target;
u_int32_t i;
if ((strlen(s) % sizeof(u_int32_t)) == 0)
target = strlen(s); /* Multiple of 4 */
else
target = strlen(s) - (strlen(s) % sizeof(u_int32_t));
for (i = 0, len = 0; len < target; len += 4)
i ^= ROUND(s + len);
return i;
}
char *
skey_fake_keyinfo(const char *username)
{
int i;
u_int ptr;
u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up;
char pbuf[SKEY_MAX_PW_LEN+1];
static char skeyprompt[SKEY_MAX_CHALLENGE+1];
char *secret = NULL;
size_t secretlen = 0;
SHA1_CTX ctx;
const char *u;
char *p;
/*
* Base first 4 chars of seed on hostname.
* Add some filler for short hostnames if necessary.
*/
if (gethostname(pbuf, sizeof(pbuf)) == -1)
*(p = pbuf) = '.';
else
for (p = pbuf; *p && isalnum(*p); p++)
if (isalpha(*p) && isupper(*p))
*p = tolower(*p);
if (*p && pbuf - p < 4)
(void)strncpy(p, "asjd", 4 - (pbuf - p));
pbuf[4] = '\0';
/* Hash the username if possible */
if ((up = SHA1Data(username, strlen(username), NULL)) != NULL) {
struct stat sb;
time_t t;
int fd;
/* Collapse the hash */
ptr = hash_collapse(up);
memset(up, 0, strlen(up));
/* See if the random file's there, else use ctime */
if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1
&& fstat(fd, &sb) == 0 &&
sb.st_size > (off_t)SKEY_MAX_SEED_LEN &&
lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN),
SEEK_SET) != -1 && read(fd, hseed,
SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
close(fd);
fd = -1;
secret = hseed;
secretlen = SKEY_MAX_SEED_LEN;
flg = 0;
} else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) {
t = sb.st_ctime;
secret = ctime(&t);
secretlen = strlen(secret);
flg = 0;
}
if (fd != -1)
close(fd);
}
/* Put that in your pipe and smoke it */
if (flg == 0) {
/* Hash secret value with username */
SHA1Init(&ctx);
SHA1Update(&ctx, secret, secretlen);
SHA1Update(&ctx, username, strlen(username));
SHA1End(&ctx, up);
/* Zero out */
memset(secret, 0, secretlen);
/* Now hash the hash */
SHA1Init(&ctx);
SHA1Update(&ctx, up, strlen(up));
SHA1End(&ctx, up);
ptr = hash_collapse(up + 4);
for (i = 4; i < 9; i++) {
pbuf[i] = (ptr % 10) + '0';
ptr /= 10;
}
pbuf[i] = '\0';
/* Sequence number */
ptr = ((up[2] + up[3]) % 99) + 1;
memset(up, 0, 20); /* SHA1 specific */
free(up);
(void)snprintf(skeyprompt, sizeof skeyprompt,
"otp-%.*s %d %.*s",
SKEY_MAX_HASHNAME_LEN,
skey_get_algorithm(),
ptr, SKEY_MAX_SEED_LEN,
pbuf);
} else {
/* Base last 8 chars of seed on username */
u = username;
i = 8;
p = &pbuf[4];
do {
if (*u == 0) {
/* Pad remainder with zeros */
while (--i >= 0)
*p++ = '0';
break;
}
*p++ = (*u++ % 10) + '0';
} while (--i != 0);
pbuf[12] = '\0';
(void)snprintf(skeyprompt, sizeof skeyprompt,
"otp-%.*s %d %.*s",
SKEY_MAX_HASHNAME_LEN,
skey_get_algorithm(),
99, SKEY_MAX_SEED_LEN, pbuf);
}
return skeyprompt;
}

282
crypto/dist/ssh/auth.c vendored Normal file
View File

@ -0,0 +1,282 @@
/* $NetBSD: auth.c,v 1.1.1.1 2000/09/28 22:09:41 thorpej Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/*
* 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.
*/
/* from OpenBSD: auth.c,v 1.10 2000/09/07 21:13:36 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: auth.c,v 1.1.1.1 2000/09/28 22:09:41 thorpej Exp $");
#endif
#include "includes.h"
#include "xmalloc.h"
#include "rsa.h"
#include "ssh.h"
#include "pty.h"
#include "packet.h"
#include "buffer.h"
#include "cipher.h"
#include "mpaux.h"
#include "servconf.h"
#include "compat.h"
#include "channels.h"
#include "match.h"
#include "bufaux.h"
#include "ssh2.h"
#include "auth.h"
#include "session.h"
#include <login_cap.h>
/* import */
extern ServerOptions options;
/*
* Check if the user is allowed to log in via ssh. If user is listed in
* DenyUsers or user's primary group is listed in DenyGroups, false will
* be returned. If AllowUsers isn't empty and user isn't listed there, or
* if AllowGroups isn't empty and user isn't listed there, false will be
* returned.
* If the user's shell is not executable, false will be returned.
* Otherwise true is returned.
*/
int
allowed_user(struct passwd *pw)
{
struct stat st;
struct group *grp;
const char *shell;
int i, match_name, match_ip;
login_cap_t *lc;
const char *hostname, *ipaddr;
char *cap_hlist, *hp;
hostname = get_canonical_hostname();
ipaddr = get_remote_ipaddr();
/* Shouldn't be called if pw is NULL, but better safe than sorry... */
if (pw == NULL)
goto denied;
lc = login_getclass(pw->pw_class);
/*
* Check the deny list.
*/
cap_hlist = login_getcapstr(lc, "host.deny", NULL, NULL);
if (cap_hlist != NULL) {
hp = strtok(cap_hlist, ",");
while (hp != NULL) {
match_name = match_hostname(hostname,
hp, strlen(hp));
match_ip = match_hostname(ipaddr,
hp, strlen(hp));
/*
* Only a positive match here causes a "deny".
*/
if (match_name > 0 || match_ip > 0) {
free(cap_hlist);
login_close(lc);
goto denied;
}
hp = strtok(NULL, ",");
}
free(cap_hlist);
}
/*
* Check the allow list. If the allow list exists, and the
* remote host is not in it, the user is implicitly denied.
*/
cap_hlist = login_getcapstr(lc, "host.allow", NULL, NULL);
if (cap_hlist != NULL) {
hp = strtok(cap_hlist, ",");
if (hp == NULL) {
/* Just in case there's an empty string... */
free(cap_hlist);
login_close(lc);
goto denied;
}
while (hp != NULL) {
match_name = match_hostname(hostname,
hp, strlen(hp));
match_ip = match_hostname(ipaddr,
hp, strlen(hp));
/*
* Negative match causes an immediate "deny".
* Positive match causes us to break out
* of the loop (allowing a fallthrough).
*/
if (match_name < 0 || match_ip < 0) {
free(cap_hlist);
login_close(lc);
goto denied;
}
if (match_name > 0 || match_ip > 0)
break;
}
free(cap_hlist);
if (hp == NULL) {
login_close(lc);
goto denied;
}
}
login_close(lc);
/*
* Get the shell from the password data. An empty shell field is
* legal, and means /bin/sh.
*/
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
/*
* Deny if shell does not exists or is not executable.
* XXX Should check to see if it is executable by the
* XXX requesting user. --thorpej
*/
if (stat(shell, &st) != 0)
goto denied;
if (S_ISREG(st.st_mode) == 0 ||
(st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0)
goto denied;
/*
* XXX Consider nuking {Allow,Deny}{Users,Groups}. We have the
* XXX login_cap(3) mechanism which covers all other types of
* XXX logins, too.
*/
/* Return false if user is listed in DenyUsers */
if (options.num_deny_users > 0) {
if (pw->pw_name == NULL)
goto denied;
for (i = 0; i < options.num_deny_users; i++)
if (match_pattern(pw->pw_name, options.deny_users[i]))
goto denied;
}
/* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) {
if (pw->pw_name == NULL)
goto denied;
for (i = 0; i < options.num_allow_users; i++)
if (match_pattern(pw->pw_name, options.allow_users[i]))
break;
/* i < options.num_allow_users iff we break for loop */
if (i >= options.num_allow_users)
goto denied;
}
/* Get the primary group name if we need it. Return false if it fails */
if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
grp = getgrgid(pw->pw_gid);
if (grp == NULL)
goto denied;
/* Return false if user's group is listed in DenyGroups */
if (options.num_deny_groups > 0) {
if (grp->gr_name == NULL)
goto denied;
for (i = 0; i < options.num_deny_groups; i++)
if (match_pattern(grp->gr_name,
options.deny_groups[i]))
goto denied;
}
/*
* Return false if AllowGroups isn't empty and user's group
* isn't listed there
*/
if (options.num_allow_groups > 0) {
if (grp->gr_name == NULL)
goto denied;
for (i = 0; i < options.num_allow_groups; i++)
if (match_pattern(grp->gr_name,
options.allow_groups[i]))
break;
/* i < options.num_allow_groups iff we break for
loop */
if (i >= options.num_allow_groups)
goto denied;
}
}
/* We found no reason not to let this user try to log on... */
return 1;
denied:
/* XXX Need to add notice() --thorpej */
log("Denied connection for %.200s from %.200s [%.200s] port %d.\n",
pw == NULL ? "<unknown>" : pw->pw_name, hostname, ipaddr,
get_remote_port());
return (0);
}

43
crypto/dist/ssh/auth.h vendored Normal file
View File

@ -0,0 +1,43 @@
/* $NetBSD: auth.h,v 1.1.1.1 2000/09/28 22:09:41 thorpej Exp $ */
/*
* 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 AUTH_H
#define AUTH_H
void do_authentication(void);
void do_authentication2(void);
struct passwd *
auth_get_user(void);
int allowed_user(struct passwd *);
#define AUTH_FAIL_MAX 6
#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
#endif

516
crypto/dist/ssh/auth1.c vendored Normal file
View File

@ -0,0 +1,516 @@
/* $NetBSD: auth1.c,v 1.1.1.1 2000/09/28 22:09:42 thorpej Exp $ */
/*
* 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".
*/
/* from OpenBSD: auth1.c,v 1.4 2000/09/07 20:27:49 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: auth1.c,v 1.1.1.1 2000/09/28 22:09:42 thorpej Exp $");
#endif
#include "includes.h"
#include "xmalloc.h"
#include "rsa.h"
#include "ssh.h"
#include "packet.h"
#include "buffer.h"
#include "cipher.h"
#include "mpaux.h"
#include "servconf.h"
#include "compat.h"
#include "auth.h"
#include "session.h"
/* import */
extern ServerOptions options;
extern char *forced_command;
/*
* convert ssh auth msg type into description
*/
static char *
get_authname(int type)
{
static char buf[1024];
switch (type) {
case SSH_CMSG_AUTH_PASSWORD:
return "password";
case SSH_CMSG_AUTH_RSA:
return "rsa";
case SSH_CMSG_AUTH_RHOSTS_RSA:
return "rhosts-rsa";
case SSH_CMSG_AUTH_RHOSTS:
return "rhosts";
#ifdef KRB4
case SSH_CMSG_AUTH_KERBEROS:
return "kerberos";
#endif
#ifdef SKEY
case SSH_CMSG_AUTH_TIS_RESPONSE:
return "s/key";
#endif
}
snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
return buf;
}
/*
* The user does not exist or access is denied,
* but fake indication that authentication is needed.
*/
static void
do_fake_authloop1(char *user)
{
int attempt = 0;
/* Indicate that authentication is needed. */
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
/*
* Keep reading packets, and always respond with a failure. This is
* to avoid disclosing whether such a user really exists.
*/
for (attempt = 1;; attempt++) {
/* Read a packet. This will not return if the client disconnects. */
int plen;
int type = packet_read(&plen);
#ifdef SKEY
unsigned int dlen;
char *password, *skeyinfo;
password = NULL;
/* Try to send a fake s/key challenge. */
if (options.skey_authentication == 1 &&
(skeyinfo = skey_fake_keyinfo(user)) != NULL) {
if (type == SSH_CMSG_AUTH_TIS) {
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
packet_put_string(skeyinfo, strlen(skeyinfo));
packet_send();
packet_write_wait();
continue;
} else if (type == SSH_CMSG_AUTH_PASSWORD &&
options.password_authentication &&
(password = packet_get_string(&dlen)) != NULL &&
dlen == 5 &&
strncasecmp(password, "s/key", 5) == 0 ) {
packet_send_debug(skeyinfo);
}
}
if (password != NULL)
xfree(password);
#endif
if (attempt > AUTH_FAIL_MAX)
packet_disconnect(AUTH_FAIL_MSG, user);
/*
* Send failure. This should be indistinguishable from a
* failed authentication.
*/
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
}
/* NOTREACHED */
abort();
}
/*
* read packets and try to authenticate local user *pw.
* return if authentication is successfull
*/
static void
do_authloop(struct passwd * pw)
{
int attempt = 0;
unsigned int bits;
RSA *client_host_key;
BIGNUM *n;
char *client_user, *password;
char user[1024];
unsigned int dlen;
int plen, nlen, elen;
unsigned int ulen;
int type = 0;
void (*authlog) (const char *fmt,...) = verbose;
/* Indicate that authentication is needed. */
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
for (attempt = 1;; attempt++) {
int authenticated = 0;
strlcpy(user, "", sizeof user);
/* Get a packet from the client. */
type = packet_read(&plen);
/* Process the packet. */
switch (type) {
#if defined(AFS) || defined(KRB5)
case SSH_CMSG_HAVE_KERBEROS_TGT:
if (!options.kerberos_tgt_passing) {
/* packet_get_all(); */
verbose("Kerberos TGT passing disabled.");
break;
} else {
int ret;
/* Accept Kerberos tgt. */
char *tgt = packet_get_string(&dlen);
packet_integrity_check(plen, 4 + dlen, type);
switch (options.kerberos_authentication) {
#ifdef AFS
case 4:
ret = auth_krb4_tgt(pw, tgt);
break;
#endif
#ifdef KRB5
case 5:
ret = auth_krb5_tgt(pw, tgt);
break;
#endif
default:
ret = 0;
}
if (ret == 0)
verbose("Kerberos TGT REFUSED for %s",
pw->pw_name);
xfree(tgt);
}
continue;
#endif /* AFS || KRB5 */
#if defined(AFS)
case SSH_CMSG_HAVE_AFS_TOKEN:
if (!options.afs_token_passing || !k_hasafs()) {
/* packet_get_all(); */
verbose("AFS token passing disabled.");
break;
} else {
/* Accept AFS token. */
char *token_string = packet_get_string(&dlen);
packet_integrity_check(plen, 4 + dlen, type);
if (!auth_afs_token(pw, token_string))
verbose("AFS token REFUSED for %s", pw->pw_name);
xfree(token_string);
}
continue;
#endif /* AFS */
#if defined(KRB4) || defined(KRB5)
case SSH_CMSG_AUTH_KERBEROS:
if (options.kerberos_authentication == 0) {
/* packet_get_all(); */
verbose("Kerberos authentication disabled.");
break;
}
#if defined(KRB4)
else if (options.kerberos_authentication == 4) {
/* Try Kerberos v4 authentication. */
KTEXT_ST auth;
char *tkt_user = NULL;
char *kdata = packet_get_string((unsigned int *) &auth.length);
packet_integrity_check(plen, 4 + auth.length, type);
if (auth.length < MAX_KTXT_LEN)
memcpy(auth.dat, kdata, auth.length);
xfree(kdata);
authenticated = auth_krb4(pw->pw_name, &auth,
&tkt_user);
if (authenticated) {
snprintf(user, sizeof user,
" tktuser %s", tkt_user);
xfree(tkt_user);
}
}
#endif
#if defined(KRB5)
else {
verbose("Kerberos v5 not yet supported.");
break;
}
#endif
break;
#endif /* KRB4 || KRB5 */
case SSH_CMSG_AUTH_RHOSTS:
if (!options.rhosts_authentication) {
verbose("Rhosts authentication disabled.");
break;
}
/*
* Get client user name. Note that we just have to
* trust the client; this is one reason why rhosts
* authentication is insecure. (Another is
* IP-spoofing on a local network.)
*/
client_user = packet_get_string(&ulen);
packet_integrity_check(plen, 4 + ulen, type);
/* Try to authenticate using /etc/hosts.equiv and
.rhosts. */
authenticated = auth_rhosts(pw, client_user);
snprintf(user, sizeof user, " ruser %s", client_user);
xfree(client_user);
break;
case SSH_CMSG_AUTH_RHOSTS_RSA:
if (!options.rhosts_rsa_authentication) {
verbose("Rhosts with RSA authentication disabled.");
break;
}
/*
* Get client user name. Note that we just have to
* trust the client; root on the client machine can
* claim to be any user.
*/
client_user = packet_get_string(&ulen);
/* Get the client host key. */
client_host_key = RSA_new();
if (client_host_key == NULL)
fatal("RSA_new failed");
client_host_key->e = BN_new();
client_host_key->n = BN_new();
if (client_host_key->e == NULL || client_host_key->n == NULL)
fatal("BN_new failed");
bits = packet_get_int();
packet_get_bignum(client_host_key->e, &elen);
packet_get_bignum(client_host_key->n, &nlen);
if (bits != BN_num_bits(client_host_key->n))
log("Warning: keysize mismatch for client_host_key: "
"actual %d, announced %d",
BN_num_bits(client_host_key->n), bits);
packet_integrity_check(plen,
(4 + ulen) + 4 + elen + nlen, type);
authenticated = auth_rhosts_rsa(pw, client_user,
client_host_key);
RSA_free(client_host_key);
snprintf(user, sizeof user, " ruser %s", client_user);
xfree(client_user);
break;
case SSH_CMSG_AUTH_RSA:
if (!options.rsa_authentication) {
verbose("RSA authentication disabled.");
break;
}
/* RSA authentication requested. */
n = BN_new();
packet_get_bignum(n, &nlen);
packet_integrity_check(plen, nlen, type);
authenticated = auth_rsa(pw, n);
BN_clear_free(n);
break;
case SSH_CMSG_AUTH_PASSWORD:
if (!options.password_authentication) {
verbose("Password authentication disabled.");
break;
}
/*
* Read user password. It is in plain text, but was
* transmitted over the encrypted channel so it is
* not visible to an outside observer.
*/
password = packet_get_string(&dlen);
packet_integrity_check(plen, 4 + dlen, type);
/* Try authentication with the password. */
authenticated = auth_password(pw, password);
memset(password, 0, strlen(password));
xfree(password);
break;
#ifdef SKEY
case SSH_CMSG_AUTH_TIS:
debug("rcvd SSH_CMSG_AUTH_TIS");
if (options.skey_authentication == 1) {
const char *skeyinfo =
skey_keyinfo(pw->pw_name);
if (skeyinfo != NULL) {
/*
* we send our s/key- in tis-challenge
* messages
*/
debug("sending challenge '%s'",
skeyinfo);
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
packet_put_string(skeyinfo,
strlen(skeyinfo));
packet_send();
packet_write_wait();
continue;
}
}
break;
case SSH_CMSG_AUTH_TIS_RESPONSE:
debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
if (options.skey_authentication == 1) {
char *response = packet_get_string(&dlen);
debug("skey response == '%s'", response);
packet_integrity_check(plen, 4 + dlen, type);
authenticated =
(skey_haskey(pw->pw_name) == 0 &&
skey_passcheck(pw->pw_name,
response) != -1);
xfree(response);
}
break;
#else
case SSH_CMSG_AUTH_TIS:
/* TIS Authentication is unsupported */
log("TIS authentication unsupported.");
break;
#endif
default:
/*
* Any unknown messages will be ignored (and failure
* returned) during authentication.
*/
log("Unknown message during authentication: type %d",
type);
break;
}
/*
* Check if the user is logging in as root and root logins
* are disallowed.
* Note that root login is allowed for forced commands.
*/
if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) {
if (forced_command) {
log("Root login accepted for forced command.");
} else {
authenticated = 0;
log("ROOT LOGIN REFUSED FROM %.200s",
get_canonical_hostname());
}
}
/* Raise logging level */
if (authenticated ||
attempt == AUTH_FAIL_LOG ||
type == SSH_CMSG_AUTH_PASSWORD)
authlog = log;
authlog("%s %s for %.200s from %.200s port %d%s",
authenticated ? "Accepted" : "Failed",
get_authname(type),
pw->pw_uid == 0 ? "ROOT" : pw->pw_name,
get_remote_ipaddr(),
get_remote_port(),
user);
if (authenticated)
return;
if (attempt > AUTH_FAIL_MAX)
packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
/* Send a message indicating that the authentication attempt failed. */
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
}
}
/*
* Performs authentication of an incoming connection. Session key has already
* been exchanged and encryption is enabled.
*/
void
do_authentication(void)
{
struct passwd *pw, pwcopy;
int plen;
unsigned int ulen;
char *user;
/* Get the name of the user that we wish to log in as. */
packet_read_expect(&plen, SSH_CMSG_USER);
/* Get the user name. */
user = packet_get_string(&ulen);
packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
setproctitle("%s", user);
#ifdef AFS
/* If machine has AFS, set process authentication group. */
if (k_hasafs()) {
k_setpag();
k_unlog();
}
#endif /* AFS */
/* Verify that the user is a valid user. */
pw = getpwnam(user);
if (!pw || !allowed_user(pw))
do_fake_authloop1(user);
xfree(user);
/* Take a copy of the returned structure. */
memset(&pwcopy, 0, sizeof(pwcopy));
pwcopy.pw_name = xstrdup(pw->pw_name);
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
pwcopy.pw_uid = pw->pw_uid;
pwcopy.pw_gid = pw->pw_gid;
pwcopy.pw_class = xstrdup(pw->pw_class);
pwcopy.pw_dir = xstrdup(pw->pw_dir);
pwcopy.pw_shell = xstrdup(pw->pw_shell);
pw = &pwcopy;
/*
* If we are not running as root, the user must have the same uid as
* the server.
*/
if (getuid() != 0 && pw->pw_uid != getuid())
packet_disconnect("Cannot change user when server not running as root.");
debug("Attempting authentication for %.100s.", pw->pw_name);
/* If the user has no password, accept authentication immediately. */
if (options.password_authentication &&
#if defined(KRB4) || defined(KRB5)
(!options.kerberos_authentication ||
options.kerberos_or_local_passwd) &&
#endif /* KRB4 || KRB5 */
auth_password(pw, "")) {
/* Authentication with empty password succeeded. */
log("Login for user %s from %.100s, accepted without authentication.",
pw->pw_name, get_remote_ipaddr());
} else {
/* Loop until the user has been authenticated or the
connection is closed, do_authloop() returns only if
authentication is successfull */
do_authloop(pw);
}
/* The user has been authenticated and accepted. */
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
/* Perform session preparation. */
do_authenticated(pw);
}

500
crypto/dist/ssh/auth2.c vendored Normal file
View File

@ -0,0 +1,500 @@
/* $NetBSD: auth2.c,v 1.1.1.1 2000/09/28 22:09:43 thorpej Exp $ */
/*
* 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.
*/
/* from OpenBSD: auth2.c,v 1.16 2000/09/27 21:41:34 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: auth2.c,v 1.1.1.1 2000/09/28 22:09:43 thorpej Exp $");
#endif
#include "includes.h"
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include "xmalloc.h"
#include "rsa.h"
#include "ssh.h"
#include "pathnames.h"
#include "pty.h"
#include "packet.h"
#include "buffer.h"
#include "cipher.h"
#include "servconf.h"
#include "compat.h"
#include "channels.h"
#include "bufaux.h"
#include "ssh2.h"
#include "auth.h"
#include "session.h"
#include "dispatch.h"
#include "auth.h"
#include "key.h"
#include "kex.h"
#include "dsa.h"
#include "uidswap.h"
#include "auth-options.h"
/* import */
extern ServerOptions options;
extern unsigned char *session_id2;
extern int session_id2_len;
/* protocol */
void input_service_request(int type, int plen, void *ctxt);
void input_userauth_request(int type, int plen, void *ctxt);
void protocol_error(int type, int plen, void *ctxt);
/* auth */
int ssh2_auth_none(struct passwd *pw);
int ssh2_auth_password(struct passwd *pw);
int ssh2_auth_pubkey(struct passwd *pw, char *service);
/* helper */
struct passwd* auth_set_user(char *u, char *s);
int user_dsa_key_allowed(struct passwd *pw, Key *key);
typedef struct Authctxt Authctxt;
struct Authctxt {
char *user;
char *service;
struct passwd pw;
int valid;
};
static Authctxt *authctxt = NULL;
static int userauth_success = 0;
/*
* loop until userauth_success == TRUE
*/
void
do_authentication2(void)
{
/* turn off skey/kerberos, not supported by SSH2 */
#ifdef SKEY
options.skey_authentication = 0;
#endif
#if defined(KRB4) || defined(KRB5)
options.kerberos_authentication = 0;
#endif
dispatch_init(&protocol_error);
dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
dispatch_run(DISPATCH_BLOCK, &userauth_success, NULL);
do_authenticated2();
}
void
protocol_error(int type, int plen, void *ctxt)
{
log("auth: protocol error: type %d plen %d", type, plen);
packet_start(SSH2_MSG_UNIMPLEMENTED);
packet_put_int(0);
packet_send();
packet_write_wait();
}
void
input_service_request(int type, int plen, void *ctxt)
{
unsigned int len;
int accept = 0;
char *service = packet_get_string(&len);
packet_done();
if (strcmp(service, "ssh-userauth") == 0) {
if (!userauth_success) {
accept = 1;
/* now we can handle user-auth requests */
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
}
}
/* XXX all other service requests are denied */
if (accept) {
packet_start(SSH2_MSG_SERVICE_ACCEPT);
packet_put_cstring(service);
packet_send();
packet_write_wait();
} else {
debug("bad service request %s", service);
packet_disconnect("bad service request %s", service);
}
xfree(service);
}
void
input_userauth_request(int type, int plen, void *ctxt)
{
static void (*authlog) (const char *fmt,...) = verbose;
static int attempt = 0;
unsigned int len;
int authenticated = 0;
char *user, *service, *method, *authmsg = NULL;
struct passwd *pw;
if (++attempt == AUTH_FAIL_MAX)
packet_disconnect("too many failed userauth_requests");
user = packet_get_string(&len);
service = packet_get_string(&len);
method = packet_get_string(&len);
debug("userauth-request for user %s service %s method %s", user, service, method);
/* XXX we only allow the ssh-connection service */
pw = auth_set_user(user, service);
if (pw && strcmp(service, "ssh-connection")==0) {
if (strcmp(method, "none") == 0) {
authenticated = ssh2_auth_none(pw);
} else if (strcmp(method, "password") == 0) {
authenticated = ssh2_auth_password(pw);
} else if (strcmp(method, "publickey") == 0) {
authenticated = ssh2_auth_pubkey(pw, service);
}
}
if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
authenticated = 0;
log("ROOT LOGIN REFUSED FROM %.200s",
get_canonical_hostname());
}
/* Raise logging level */
if (authenticated == 1 ||
attempt == AUTH_FAIL_LOG ||
strcmp(method, "password") == 0)
authlog = log;
/* Log before sending the reply */
if (authenticated == 1) {
authmsg = "Accepted";
} else if (authenticated == 0) {
authmsg = "Failed";
} else {
authmsg = "Postponed";
}
authlog("%s %s for %.200s from %.200s port %d ssh2",
authmsg,
method,
pw && pw->pw_uid == 0 ? "ROOT" : user,
get_remote_ipaddr(),
get_remote_port());
/* XXX todo: check if multiple auth methods are needed */
if (authenticated == 1) {
/* turn off userauth */
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error);
packet_start(SSH2_MSG_USERAUTH_SUCCESS);
packet_send();
packet_write_wait();
/* now we can break out */
userauth_success = 1;
} else if (authenticated == 0) {
packet_start(SSH2_MSG_USERAUTH_FAILURE);
packet_put_cstring("publickey,password"); /* XXX dynamic */
packet_put_char(0); /* XXX partial success, unused */
packet_send();
packet_write_wait();
}
xfree(service);
xfree(user);
xfree(method);
}
int
ssh2_auth_none(struct passwd *pw)
{
packet_done();
return auth_password(pw, "");
}
int
ssh2_auth_password(struct passwd *pw)
{
char *password;
int authenticated = 0;
int change;
unsigned int len;
change = packet_get_char();
if (change)
log("password change not supported");
password = packet_get_string(&len);
packet_done();
if (options.password_authentication &&
auth_password(pw, password) == 1)
authenticated = 1;
memset(password, 0, len);
xfree(password);
return authenticated;
}
int
ssh2_auth_pubkey(struct passwd *pw, char *service)
{
Buffer b;
Key *key;
char *pkalg, *pkblob, *sig;
unsigned int alen, blen, slen;
int have_sig;
int authenticated = 0;
if (options.dsa_authentication == 0) {
debug("pubkey auth disabled");
return 0;
}
have_sig = packet_get_char();
pkalg = packet_get_string(&alen);
if (strcmp(pkalg, KEX_DSS) != 0) {
xfree(pkalg);
log("bad pkalg %s", pkalg); /*XXX*/
return 0;
}
pkblob = packet_get_string(&blen);
key = dsa_key_from_blob(pkblob, blen);
if (key != NULL) {
if (have_sig) {
sig = packet_get_string(&slen);
packet_done();
buffer_init(&b);
if (datafellows & SSH_COMPAT_SESSIONID_ENCODING) {
buffer_put_string(&b, session_id2, session_id2_len);
} else {
buffer_append(&b, session_id2, session_id2_len);
}
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
buffer_put_cstring(&b, pw->pw_name);
buffer_put_cstring(&b,
datafellows & SSH_BUG_PUBKEYAUTH ?
"ssh-userauth" :
service);
buffer_put_cstring(&b, "publickey");
buffer_put_char(&b, have_sig);
buffer_put_cstring(&b, KEX_DSS);
buffer_put_string(&b, pkblob, blen);
#ifdef DEBUG_DSS
buffer_dump(&b);
#endif
/* test for correct signature */
if (user_dsa_key_allowed(pw, key) &&
dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
authenticated = 1;
buffer_clear(&b);
xfree(sig);
} else {
packet_done();
debug("test key...");
/* test whether pkalg/pkblob are acceptable */
/* XXX fake reply and always send PK_OK ? */
/*
* XXX this allows testing whether a user is allowed
* to login: if you happen to have a valid pubkey this
* message is sent. the message is NEVER sent at all
* if a user is not allowed to login. is this an
* issue? -markus
*/
if (user_dsa_key_allowed(pw, key)) {
packet_start(SSH2_MSG_USERAUTH_PK_OK);
packet_put_string(pkalg, alen);
packet_put_string(pkblob, blen);
packet_send();
packet_write_wait();
authenticated = -1;
}
}
key_free(key);
}
xfree(pkalg);
xfree(pkblob);
return authenticated;
}
/* set and get current user */
struct passwd*
auth_get_user(void)
{
return (authctxt != NULL && authctxt->valid) ? &authctxt->pw : NULL;
}
struct passwd*
auth_set_user(char *u, char *s)
{
struct passwd *pw, *copy;
if (authctxt == NULL) {
authctxt = xmalloc(sizeof(*authctxt));
authctxt->valid = 0;
authctxt->user = xstrdup(u);
authctxt->service = xstrdup(s);
setproctitle("%s", u);
pw = getpwnam(u);
if (!pw || !allowed_user(pw)) {
log("auth_set_user: illegal user %s", u);
return NULL;
}
copy = &authctxt->pw;
memset(copy, 0, sizeof(*copy));
copy->pw_name = xstrdup(pw->pw_name);
copy->pw_passwd = xstrdup(pw->pw_passwd);
copy->pw_uid = pw->pw_uid;
copy->pw_gid = pw->pw_gid;
copy->pw_class = xstrdup(pw->pw_class);
copy->pw_dir = xstrdup(pw->pw_dir);
copy->pw_shell = xstrdup(pw->pw_shell);
authctxt->valid = 1;
} else {
if (strcmp(u, authctxt->user) != 0 ||
strcmp(s, authctxt->service) != 0) {
log("auth_set_user: missmatch: (%s,%s)!=(%s,%s)",
u, s, authctxt->user, authctxt->service);
return NULL;
}
}
return auth_get_user();
}
/* return 1 if user allows given key */
int
user_dsa_key_allowed(struct passwd *pw, Key *key)
{
char line[8192], file[1024];
int found_key = 0;
unsigned int bits = -1;
FILE *f;
unsigned long linenum = 0;
struct stat st;
Key *found;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw->pw_uid);
/* The authorized keys. */
snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
_PATH_SSH_USER_PERMITTED_KEYS2);
/* Fail quietly if file does not exist */
if (stat(file, &st) < 0) {
/* Restore the privileged uid. */
restore_uid();
return 0;
}
/* Open the file containing the authorized keys. */
f = fopen(file, "r");
if (!f) {
/* Restore the privileged uid. */
restore_uid();
return 0;
}
if (options.strict_modes) {
int fail = 0;
char buf[1024];
/* Check open file in order to avoid open/stat races */
if (fstat(fileno(f), &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf,
"%s authentication refused for %.100s: "
"bad ownership or modes for '%s'.",
key_type(key), pw->pw_name, file);
fail = 1;
} else {
/* Check path to _PATH_SSH_USER_PERMITTED_KEYS */
int i;
static const char *check[] = {
"", _PATH_SSH_USER_DIR, NULL
};
for (i = 0; check[i]; i++) {
snprintf(line, sizeof line, "%.500s/%.100s",
pw->pw_dir, check[i]);
if (stat(line, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0) {
snprintf(buf, sizeof buf,
"%s authentication refused for %.100s: "
"bad ownership or modes for '%s'.",
key_type(key), pw->pw_name, line);
fail = 1;
break;
}
}
}
if (fail) {
fclose(f);
log("%s",buf);
restore_uid();
return 0;
}
}
found_key = 0;
found = key_new(key->type);
while (fgets(line, sizeof(line), f)) {
char *cp, *options = NULL;
linenum++;
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '\n' || *cp == '#')
continue;
bits = key_read(found, &cp);
if (bits == 0) {
/* no key? check if there are options for this key */
int quoted = 0;
options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
/* Skip remaining whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
bits = key_read(found, &cp);
if (bits == 0) {
/* still no key? advance to next line*/
continue;
}
}
if (key_equal(found, key) &&
auth_parse_options(pw, options, linenum) == 1) {
found_key = 1;
debug("matching key found: file %s, line %ld",
file, linenum);
break;
}
}
restore_uid();
fclose(f);
key_free(found);
return found_key;
}

553
crypto/dist/ssh/authfd.c vendored Normal file
View File

@ -0,0 +1,553 @@
/* $NetBSD: authfd.c,v 1.1.1.1 2000/09/28 22:09:44 thorpej 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.
*/
/* from OpenBSD: authfd.c,v 1.28 2000/09/21 11:07:50 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: authfd.c,v 1.1.1.1 2000/09/28 22:09:44 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "rsa.h"
#include "buffer.h"
#include "bufaux.h"
#include "xmalloc.h"
#include "getput.h"
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/evp.h>
#include "key.h"
#include "authfd.h"
#include "kex.h"
#include "dsa.h"
#include "compat.h"
/* helper */
int decode_reply(int type);
/* Returns the number of the authentication fd, or -1 if there is none. */
int
ssh_get_authentication_socket()
{
const char *authsocket;
int sock, len;
struct sockaddr_un sunaddr;
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
if (!authsocket)
return -1;
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
sunaddr.sun_len = len = SUN_LEN(&sunaddr)+1;
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;
}
if (connect(sock, (struct sockaddr *) & sunaddr, len) < 0) {
close(sock);
return -1;
}
return sock;
}
static int
ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply)
{
int l, len;
char buf[1024];
/* Get the length of the message, and format it in the buffer. */
len = buffer_len(request);
PUT_32BIT(buf, len);
/* Send the length and then the packet to the agent. */
if (atomic_write(auth->fd, buf, 4) != 4 ||
atomic_write(auth->fd, buffer_ptr(request),
buffer_len(request)) != buffer_len(request)) {
error("Error writing to authentication socket.");
return 0;
}
/*
* Wait for response from the agent. First read the length of the
* response packet.
*/
len = 4;
while (len > 0) {
l = read(auth->fd, buf + 4 - len, len);
if (l <= 0) {
error("Error reading response length from authentication socket.");
return 0;
}
len -= l;
}
/* Extract the length, and check it for sanity. */
len = GET_32BIT(buf);
if (len > 256 * 1024)
fatal("Authentication response too long: %d", len);
/* Read the rest of the response in to the buffer. */
buffer_clear(reply);
while (len > 0) {
l = len;
if (l > sizeof(buf))
l = sizeof(buf);
l = read(auth->fd, buf, l);
if (l <= 0) {
error("Error reading response from authentication socket.");
return 0;
}
buffer_append(reply, (char *) 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()
{
AuthenticationConnection *auth;
int sock;
sock = ssh_get_authentication_socket();
/*
* Fail if we couldn't obtain a connection. This happens if we
* exited due to a timeout.
*/
if (sock < 0)
return NULL;
auth = xmalloc(sizeof(*auth));
auth->fd = sock;
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)
{
buffer_free(&auth->identities);
close(auth->fd);
xfree(auth);
}
/*
* Returns the first authentication identity held by the agent.
*/
Key *
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, 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 NULL;
}
/*
* Send a message to the agent requesting for a list of the
* identities it can represent.
*/
buffer_init(&request);
buffer_put_char(&request, code1);
buffer_clear(&auth->identities);
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
buffer_free(&request);
return NULL;
}
buffer_free(&request);
/* Get message type, and verify that we got a proper answer. */
type = buffer_get_char(&auth->identities);
if (type == SSH_AGENT_FAILURE) {
return NULL;
} else if (type != code2) {
fatal("Bad authentication reply message type: %d", type);
}
/* Get the number of entries in the response and check it for sanity. */
auth->howmany = buffer_get_int(&auth->identities);
if (auth->howmany > 1024)
fatal("Too many identities in authentication reply: %d\n",
auth->howmany);
/* Return the first entry (if any). */
return ssh_get_next_identity(auth, comment, version);
}
Key *
ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
{
unsigned int bits;
unsigned char *blob;
unsigned 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 = key_new(KEY_RSA);
bits = buffer_get_int(&auth->identities);
buffer_get_bignum(&auth->identities, key->rsa->e);
buffer_get_bignum(&auth->identities, key->rsa->n);
*comment = buffer_get_string(&auth->identities, NULL);
if (bits != BN_num_bits(key->rsa->n))
log("Warning: identity keysize mismatch: actual %d, announced %u",
BN_num_bits(key->rsa->n), bits);
break;
case 2:
blob = buffer_get_string(&auth->identities, &blen);
*comment = buffer_get_string(&auth->identities, NULL);
key = dsa_key_from_blob(blob, blen);
xfree(blob);
break;
default:
return NULL;
break;
}
/* 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,
unsigned char session_id[16],
unsigned int response_type,
unsigned char response[16])
{
Buffer buffer;
int success = 0;
int i;
int type;
if (key->type != KEY_RSA)
return 0;
if (response_type == 0) {
log("Compatibility with ssh protocol version 1.0 no longer supported.");
return 0;
}
buffer_init(&buffer);
buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
buffer_put_int(&buffer, BN_num_bits(key->rsa->n));
buffer_put_bignum(&buffer, key->rsa->e);
buffer_put_bignum(&buffer, key->rsa->n);
buffer_put_bignum(&buffer, challenge);
buffer_append(&buffer, (char *) session_id, 16);
buffer_put_int(&buffer, response_type);
if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
buffer_free(&buffer);
return 0;
}
type = buffer_get_char(&buffer);
if (type == SSH_AGENT_FAILURE) {
log("Agent admitted failure to authenticate using the key.");
} else if (type != SSH_AGENT_RSA_RESPONSE) {
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] = buffer_get_char(&buffer);
}
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,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen)
{
extern int datafellows;
Buffer msg;
unsigned char *blob;
unsigned int blen;
int type, flags = 0;
int ret = -1;
if (dsa_make_key_blob(key, &blob, &blen) == 0)
return -1;
if (datafellows & SSH_BUG_SIGBLOB)
flags = SSH_AGENT_OLD_SIGNATURE;
buffer_init(&msg);
buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
buffer_put_string(&msg, blob, blen);
buffer_put_string(&msg, data, datalen);
buffer_put_int(&msg, flags);
xfree(blob);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return -1;
}
type = buffer_get_char(&msg);
if (type == SSH_AGENT_FAILURE) {
log("Agent admitted failure to sign using the key.");
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
fatal("Bad authentication response: %d", type);
} else {
ret = 0;
*sigp = buffer_get_string(&msg, lenp);
}
buffer_free(&msg);
return ret;
}
/* Encode key for a message to the agent. */
static void
ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment)
{
buffer_clear(b);
buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
buffer_put_int(b, BN_num_bits(key->n));
buffer_put_bignum(b, key->n);
buffer_put_bignum(b, key->e);
buffer_put_bignum(b, key->d);
/* To keep within the protocol: p < q for ssh. in SSL p > q */
buffer_put_bignum(b, key->iqmp); /* ssh key->u */
buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */
buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */
buffer_put_string(b, comment, strlen(comment));
}
static void
ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
{
buffer_clear(b);
buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
buffer_put_cstring(b, KEX_DSS);
buffer_put_bignum2(b, key->p);
buffer_put_bignum2(b, key->q);
buffer_put_bignum2(b, key->g);
buffer_put_bignum2(b, key->pub_key);
buffer_put_bignum2(b, key->priv_key);
buffer_put_string(b, comment, strlen(comment));
}
/*
* Adds an identity to the authentication server. This call is not meant to
* be used by normal applications.
*/
int
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
{
Buffer msg;
int type;
buffer_init(&msg);
switch (key->type) {
case KEY_RSA:
ssh_encode_identity_rsa(&msg, key->rsa, comment);
break;
case KEY_DSA:
ssh_encode_identity_dsa(&msg, key->dsa, comment);
break;
default:
buffer_free(&msg);
return 0;
break;
}
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;
}
type = buffer_get_char(&msg);
buffer_free(&msg);
return decode_reply(type);
}
/*
* 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;
unsigned char *blob;
unsigned int blen;
buffer_init(&msg);
if (key->type == KEY_RSA) {
buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
buffer_put_int(&msg, BN_num_bits(key->rsa->n));
buffer_put_bignum(&msg, key->rsa->e);
buffer_put_bignum(&msg, key->rsa->n);
} else if (key->type == KEY_DSA) {
dsa_make_key_blob(key, &blob, &blen);
buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
buffer_put_string(&msg, blob, blen);
xfree(blob);
} else {
buffer_free(&msg);
return 0;
}
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;
}
type = buffer_get_char(&msg);
buffer_free(&msg);
return 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;
buffer_init(&msg);
buffer_put_char(&msg, code);
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
return 0;
}
type = buffer_get_char(&msg);
buffer_free(&msg);
return decode_reply(type);
}
int
decode_reply(int type)
{
switch (type) {
case SSH_AGENT_FAILURE:
log("SSH_AGENT_FAILURE");
return 0;
case SSH_AGENT_SUCCESS:
return 1;
default:
fatal("Bad response from authentication agent: %d", type);
}
/* NOTREACHED */
return 0;
}

131
crypto/dist/ssh/authfd.h vendored Normal file
View File

@ -0,0 +1,131 @@
/* $NetBSD: authfd.h,v 1.1.1.1 2000/09/28 22:09:44 thorpej 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".
*/
/* from OpenBSD: authfd.h,v 1.12 2000/09/21 11:07:51 markus Exp */
#ifndef AUTHFD_H
#define AUTHFD_H
#include "buffer.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
#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
#define SSH_AGENT_OLD_SIGNATURE 0x01
typedef struct {
int fd;
Buffer identities;
int howmany;
} AuthenticationConnection;
/* Returns the number of the authentication fd, or -1 if there is none. */
int ssh_get_authentication_socket(void);
/*
* This should be called for any descriptor returned by
* ssh_get_authentication_socket(). Depending on the way the descriptor was
* obtained, this may close the descriptor.
*/
void ssh_close_authentication_socket(int authfd);
/*
* Opens and connects a private socket for communication with the
* authentication agent. Returns NULL if an error occurred and the
* connection could not be opened. The connection should be closed by the
* caller by calling ssh_close_authentication_connection().
*/
AuthenticationConnection *ssh_get_authentication_connection(void);
/*
* Closes the connection to the authentication agent and frees any associated
* memory.
*/
void ssh_close_authentication_connection(AuthenticationConnection *auth);
/*
* Returns the first authentication identity held by the agent or NULL if
* no identies are available. Caller must free comment and key.
* Note that you cannot mix calls with different versions.
*/
Key *ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version);
/*
* Returns the next authentication identity for the agent. Other functions
* can be called between this and ssh_get_first_identity or two calls of this
* function. This returns NULL if there are no more identities. The caller
* must free key and comment after a successful return.
*/
Key *ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version);
/*
* Requests the agent to decrypt the given challenge. Returns true if the
* agent claims it was able to decrypt it.
*/
int
ssh_decrypt_challenge(AuthenticationConnection *auth,
Key *key, BIGNUM * challenge,
unsigned char session_id[16],
unsigned int response_type,
unsigned char response[16]);
/* Requests the agent to sign data using key */
int
ssh_agent_sign(AuthenticationConnection *auth,
Key *key,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen);
/*
* Adds an identity to the authentication server. This call is not meant to
* be used by normal applications. This returns true if the identity was
* successfully added.
*/
int
ssh_add_identity(AuthenticationConnection *auth, Key *key,
const char *comment);
/*
* Removes the identity from the authentication server. This call is not
* meant to be used by normal applications. This returns true if the
* identity was successfully added.
*/
int ssh_remove_identity(AuthenticationConnection *auth, Key *key);
/*
* Removes all identities from the authentication agent. This call is not
* meant to be used by normal applications. This returns true if the
* operation was successful.
*/
int ssh_remove_all_identities(AuthenticationConnection *auth, int version);
#endif /* AUTHFD_H */

580
crypto/dist/ssh/authfile.c vendored Normal file
View File

@ -0,0 +1,580 @@
/* $NetBSD: authfile.c,v 1.1.1.1 2000/09/28 22:09:46 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* This file contains functions for reading and writing identity files, and
* for reading the passphrase from the user.
*
* 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.
*/
/* from OpenBSD: authfile.c,v 1.19 2000/09/07 20:27:49 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: authfile.c,v 1.1.1.1 2000/09/28 22:09:46 thorpej Exp $");
#endif
#include "includes.h"
#include <openssl/bn.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
#include "cipher.h"
#include "ssh.h"
#include "key.h"
#include "authfile.h"
/* Version identification string for identity files. */
#define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n"
/*
* Saves the authentication (private) key in a file, encrypting it with
* passphrase. The identification of the file (lowest 64 bits of n) will
* precede the key to provide identification of the key without needing a
* passphrase.
*/
static int
save_private_key_rsa(const char *filename, const char *passphrase,
RSA *key, const char *comment)
{
Buffer buffer, encrypted;
char buf[100], *cp;
int fd, i;
CipherContext cipher;
int cipher_type;
u_int32_t rand;
/*
* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
* to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
*/
if (strcmp(passphrase, "") == 0)
cipher_type = SSH_CIPHER_NONE;
else
cipher_type = SSH_AUTHFILE_CIPHER;
/* This buffer is used to built the secret part of the private key. */
buffer_init(&buffer);
/* Put checkbytes for checking passphrase validity. */
/* XXXthorpej */
RAND_pseudo_bytes((u_char *)&rand, sizeof(rand));
buf[0] = rand & 0xff;
buf[1] = (rand >> 8) & 0xff;
buf[2] = buf[0];
buf[3] = buf[1];
buffer_append(&buffer, buf, 4);
/*
* Store the private key (n and e will not be stored because they
* will be stored in plain text, and storing them also in encrypted
* format would just give known plaintext).
*/
buffer_put_bignum(&buffer, key->d);
buffer_put_bignum(&buffer, key->iqmp);
buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */
buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */
/* Pad the part to be encrypted until its size is a multiple of 8. */
while (buffer_len(&buffer) % 8 != 0)
buffer_put_char(&buffer, 0);
/* This buffer will be used to contain the data in the file. */
buffer_init(&encrypted);
/* First store keyfile id string. */
cp = AUTHFILE_ID_STRING;
for (i = 0; cp[i]; i++)
buffer_put_char(&encrypted, cp[i]);
buffer_put_char(&encrypted, 0);
/* Store cipher type. */
buffer_put_char(&encrypted, cipher_type);
buffer_put_int(&encrypted, 0); /* For future extension */
/* Store public key. This will be in plain text. */
buffer_put_int(&encrypted, BN_num_bits(key->n));
buffer_put_bignum(&encrypted, key->n);
buffer_put_bignum(&encrypted, key->e);
buffer_put_string(&encrypted, comment, strlen(comment));
/* Allocate space for the private part of the key in the buffer. */
buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
cipher_set_key_string(&cipher, cipher_type, passphrase);
cipher_encrypt(&cipher, (unsigned char *) cp,
(unsigned char *) buffer_ptr(&buffer),
buffer_len(&buffer));
memset(&cipher, 0, sizeof(cipher));
/* Destroy temporary data. */
memset(buf, 0, sizeof(buf));
buffer_free(&buffer);
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0)
return 0;
if (write(fd, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
buffer_len(&encrypted)) {
debug("Write to key file %.200s failed: %.100s", filename,
strerror(errno));
buffer_free(&encrypted);
close(fd);
remove(filename);
return 0;
}
close(fd);
buffer_free(&encrypted);
return 1;
}
/* save DSA key in OpenSSL PEM format */
static int
save_private_key_dsa(const char *filename, const char *passphrase,
DSA *dsa, const char *comment)
{
FILE *fp;
int fd;
int success = 1;
int len = strlen(passphrase);
if (len > 0 && len <= 4) {
error("passphrase too short: %d bytes", len);
errno = 0;
return 0;
}
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) {
debug("open %s failed", filename);
return 0;
}
fp = fdopen(fd, "w");
if (fp == NULL ) {
debug("fdopen %s failed", filename);
close(fd);
return 0;
}
if (len > 0) {
if (!PEM_write_DSAPrivateKey(fp, dsa, EVP_des_ede3_cbc(),
(char *)passphrase, strlen(passphrase), NULL, NULL))
success = 0;
} else {
if (!PEM_write_DSAPrivateKey(fp, dsa, NULL,
NULL, 0, NULL, NULL))
success = 0;
}
fclose(fp);
return success;
}
int
save_private_key(const char *filename, const char *passphrase, Key *key,
const char *comment)
{
switch (key->type) {
case KEY_RSA:
return save_private_key_rsa(filename, passphrase, key->rsa, comment);
break;
case KEY_DSA:
return save_private_key_dsa(filename, passphrase, key->dsa, comment);
break;
default:
break;
}
return 0;
}
/*
* Loads the public part of the key file. Returns 0 if an error was
* encountered (the file does not exist or is not readable), and non-zero
* otherwise.
*/
static int
load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
{
int fd, i;
off_t len;
Buffer buffer;
char *cp;
fd = open(filename, O_RDONLY);
if (fd < 0)
return 0;
len = lseek(fd, (off_t) 0, SEEK_END);
lseek(fd, (off_t) 0, SEEK_SET);
buffer_init(&buffer);
buffer_append_space(&buffer, &cp, len);
if (read(fd, cp, (size_t) len) != (size_t) len) {
debug("Read from key file %.200s failed: %.100s", filename,
strerror(errno));
buffer_free(&buffer);
close(fd);
return 0;
}
close(fd);
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
/*
* Make sure it begins with the id string. Consume the id string
* from the buffer.
*/
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) {
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
/* Skip cipher type and reserved data. */
(void) buffer_get_char(&buffer); /* cipher type */
(void) buffer_get_int(&buffer); /* reserved */
/* Read the public key from the buffer. */
buffer_get_int(&buffer);
/* XXX alloc */
if (pub->n == NULL)
pub->n = BN_new();
buffer_get_bignum(&buffer, pub->n);
/* XXX alloc */
if (pub->e == NULL)
pub->e = BN_new();
buffer_get_bignum(&buffer, pub->e);
if (comment_return)
*comment_return = buffer_get_string(&buffer, NULL);
/* The encrypted private part is not parsed by this function. */
buffer_free(&buffer);
return 1;
}
/* load public key from private-key file */
int
load_public_key(const char *filename, Key * key, char **comment_return)
{
switch (key->type) {
case KEY_RSA:
return load_public_key_rsa(filename, key->rsa, comment_return);
break;
case KEY_DSA:
default:
break;
}
return 0;
}
/*
* Loads the private key from the file. Returns 0 if an error is encountered
* (file does not exist or is not readable, or passphrase is bad). This
* initializes the private key.
* Assumes we are called under uid of the owner of the file.
*/
static int
load_private_key_rsa(int fd, const char *filename,
const char *passphrase, RSA * prv, char **comment_return)
{
int i, check1, check2, cipher_type;
off_t len;
Buffer buffer, decrypted;
char *cp;
CipherContext cipher;
BN_CTX *ctx;
BIGNUM *aux;
len = lseek(fd, (off_t) 0, SEEK_END);
lseek(fd, (off_t) 0, SEEK_SET);
buffer_init(&buffer);
buffer_append_space(&buffer, &cp, len);
if (read(fd, cp, (size_t) len) != (size_t) len) {
debug("Read from key file %.200s failed: %.100s", filename,
strerror(errno));
buffer_free(&buffer);
close(fd);
return 0;
}
close(fd);
/* Check that it is at least big enought to contain the ID string. */
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
/*
* Make sure it begins with the id string. Consume the id string
* from the buffer.
*/
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) {
debug("Bad key file %.200s.", filename);
buffer_free(&buffer);
return 0;
}
/* Read cipher type. */
cipher_type = buffer_get_char(&buffer);
(void) buffer_get_int(&buffer); /* Reserved data. */
/* Read the public key from the buffer. */
buffer_get_int(&buffer);
prv->n = BN_new();
buffer_get_bignum(&buffer, prv->n);
prv->e = BN_new();
buffer_get_bignum(&buffer, prv->e);
if (comment_return)
*comment_return = buffer_get_string(&buffer, NULL);
else
xfree(buffer_get_string(&buffer, NULL));
/* Check that it is a supported cipher. */
if (((cipher_mask1() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) &
(1 << cipher_type)) == 0) {
debug("Unsupported cipher %.100s used in key file %.200s.",
cipher_name(cipher_type), filename);
buffer_free(&buffer);
goto fail;
}
/* Initialize space for decrypted data. */
buffer_init(&decrypted);
buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
cipher_set_key_string(&cipher, cipher_type, passphrase);
cipher_decrypt(&cipher, (unsigned char *) cp,
(unsigned char *) buffer_ptr(&buffer),
buffer_len(&buffer));
buffer_free(&buffer);
check1 = buffer_get_char(&decrypted);
check2 = buffer_get_char(&decrypted);
if (check1 != buffer_get_char(&decrypted) ||
check2 != buffer_get_char(&decrypted)) {
if (strcmp(passphrase, "") != 0)
debug("Bad passphrase supplied for key file %.200s.", filename);
/* Bad passphrase. */
buffer_free(&decrypted);
fail:
BN_clear_free(prv->n);
prv->n = NULL;
BN_clear_free(prv->e);
prv->e = NULL;
if (comment_return)
xfree(*comment_return);
return 0;
}
/* Read the rest of the private key. */
prv->d = BN_new();
buffer_get_bignum(&decrypted, prv->d);
prv->iqmp = BN_new();
buffer_get_bignum(&decrypted, prv->iqmp); /* u */
/* in SSL and SSH p and q are exchanged */
prv->q = BN_new();
buffer_get_bignum(&decrypted, prv->q); /* p */
prv->p = BN_new();
buffer_get_bignum(&decrypted, prv->p); /* q */
ctx = BN_CTX_new();
aux = BN_new();
BN_sub(aux, prv->q, BN_value_one());
prv->dmq1 = BN_new();
BN_mod(prv->dmq1, prv->d, aux, ctx);
BN_sub(aux, prv->p, BN_value_one());
prv->dmp1 = BN_new();
BN_mod(prv->dmp1, prv->d, aux, ctx);
BN_clear_free(aux);
BN_CTX_free(ctx);
buffer_free(&decrypted);
return 1;
}
static int
load_private_key_dsa(int fd, const char *passphrase, Key *k, char **comment_return)
{
DSA *dsa;
BIO *in;
FILE *fp;
in = BIO_new(BIO_s_file());
if (in == NULL) {
error("BIO_new failed");
return 0;
}
fp = fdopen(fd, "r");
if (fp == NULL) {
error("fdopen failed");
return 0;
}
BIO_set_fp(in, fp, BIO_NOCLOSE);
dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, (char *)passphrase);
if (dsa == NULL) {
debug("PEM_read_bio_DSAPrivateKey failed");
} else {
/* replace k->dsa with loaded key */
DSA_free(k->dsa);
k->dsa = dsa;
}
BIO_free(in);
fclose(fp);
if (comment_return)
*comment_return = xstrdup("dsa w/o comment");
debug("read DSA private key done");
#ifdef DEBUG_DSS
DSA_print_fp(stderr, dsa, 8);
#endif
return dsa != NULL ? 1 : 0;
}
int
load_private_key(const char *filename, const char *passphrase, Key *key,
char **comment_return)
{
int fd;
int ret = 0;
struct stat st;
fd = open(filename, O_RDONLY);
if (fd < 0)
return 0;
/* check owner and modes */
if (fstat(fd, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != getuid()) ||
(st.st_mode & 077) != 0) {
close(fd);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("Bad ownership or mode(0%3.3o) for '%s'.",
st.st_mode & 0777, filename);
error("It is recommended that your private key files are NOT accessible by others.");
return 0;
}
switch (key->type) {
case KEY_RSA:
if (key->rsa->e != NULL) {
BN_clear_free(key->rsa->e);
key->rsa->e = NULL;
}
if (key->rsa->n != NULL) {
BN_clear_free(key->rsa->n);
key->rsa->n = NULL;
}
ret = load_private_key_rsa(fd, filename, passphrase,
key->rsa, comment_return);
break;
case KEY_DSA:
ret = load_private_key_dsa(fd, passphrase, key, comment_return);
default:
break;
}
close(fd);
return ret;
}
static int
do_load_public_key(const char *filename, Key *k, char **commentp)
{
FILE *f;
unsigned int bits;
char line[1024];
char *cp;
f = fopen(filename, "r");
if (f != NULL) {
while (fgets(line, sizeof(line), f)) {
line[sizeof(line)-1] = '\0';
cp = line;
switch(*cp){
case '#':
case '\n':
case '\0':
continue;
}
/* Skip leading whitespace. */
for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
;
if (*cp) {
bits = key_read(k, &cp);
if (bits != 0) {
if (commentp)
*commentp=xstrdup(filename);
fclose(f);
return 1;
}
}
}
fclose(f);
}
return 0;
}
/* load public key from pubkey file */
int
try_load_public_key(const char *filename, Key *k, char **commentp)
{
char pub[MAXPATHLEN];
if (do_load_public_key(filename, k, commentp) == 1)
return 1;
if (strlcpy(pub, filename, sizeof pub) >= MAXPATHLEN)
return 0;
if (strlcat(pub, ".pub", sizeof pub) >= MAXPATHLEN)
return 0;
if (do_load_public_key(pub, k, commentp) == 1)
return 1;
return 0;
}

50
crypto/dist/ssh/authfile.h vendored Normal file
View File

@ -0,0 +1,50 @@
/* $NetBSD: authfile.h,v 1.1.1.1 2000/09/28 22:09:46 thorpej 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 AUTHFILE_H
#define AUTHFILE_H
/*
* Saves the authentication (private) key in a file, encrypting it with
* passphrase.
* For RSA keys: The identification of the file (lowest 64 bits of n)
* will precede the key to provide identification of the key without
* needing a passphrase.
*/
int
save_private_key(const char *filename, const char *passphrase,
Key * private_key, const char *comment);
/*
* Loads the public part of the key file (public key and comment). Returns 0
* if an error occurred; zero if the public key was successfully read. The
* comment of the key is returned in comment_return if it is non-NULL; the
* caller must free the value with xfree.
*/
int load_public_key(const char *filename, Key * pub, char **comment_return);
int try_load_public_key(const char *filename, Key * pub, char **comment_return);
/*
* Loads the private key from the file. Returns 0 if an error is encountered
* (file does not exist or is not readable, or passphrase is bad). This
* initializes the private key. The comment of the key is returned in
* comment_return if it is non-NULL; the caller must free the value with
* xfree.
*/
int
load_private_key(const char *filename, const char *passphrase,
Key * private_key, char **comment_return);
#endif

237
crypto/dist/ssh/bufaux.c vendored Normal file
View File

@ -0,0 +1,237 @@
/* $NetBSD: bufaux.c,v 1.1.1.1 2000/09/28 22:09:46 thorpej 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.
*/
/* from OpenBSD: bufaux.c,v 1.13 2000/09/07 20:27:50 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: bufaux.c,v 1.1.1.1 2000/09/28 22:09:46 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include <openssl/bn.h>
#include "bufaux.h"
#include "xmalloc.h"
#include "getput.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.
*/
void
buffer_put_bignum(Buffer *buffer, BIGNUM *value)
{
int bits = BN_num_bits(value);
int bin_size = (bits + 7) / 8;
char unsigned *buf = xmalloc(bin_size);
int oi;
char msg[2];
/* Get the value of in binary */
oi = BN_bn2bin(value, buf);
if (oi != bin_size)
fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
oi, bin_size);
/* Store the number of bits in the buffer in two bytes, msb first. */
PUT_16BIT(msg, bits);
buffer_append(buffer, msg, 2);
/* Store the binary data. */
buffer_append(buffer, (char *)buf, oi);
memset(buf, 0, bin_size);
xfree(buf);
}
/*
* Retrieves an BIGNUM from the buffer.
*/
int
buffer_get_bignum(Buffer *buffer, BIGNUM *value)
{
int bits, bytes;
unsigned char buf[2], *bin;
/* Get the number for bits. */
buffer_get(buffer, (char *) buf, 2);
bits = GET_16BIT(buf);
/* Compute the number of binary bytes that follow. */
bytes = (bits + 7) / 8;
if (buffer_len(buffer) < bytes)
fatal("buffer_get_bignum: input buffer too small");
bin = (unsigned char*) buffer_ptr(buffer);
BN_bin2bn(bin, bytes, value);
buffer_consume(buffer, bytes);
return 2 + bytes;
}
/*
* Stores an BIGNUM in the buffer in SSH2 format.
*/
void
buffer_put_bignum2(Buffer *buffer, BIGNUM *value)
{
int bytes = BN_num_bytes(value) + 1;
unsigned char *buf = xmalloc(bytes);
int oi;
int hasnohigh = 0;
buf[0] = '\0';
/* Get the value of in binary */
oi = BN_bn2bin(value, buf+1);
if (oi != bytes-1)
fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
oi, bytes);
hasnohigh = (buf[1] & 0x80) ? 0 : 1;
if (value->neg) {
/**XXX should be two's-complement */
int i, carry;
unsigned char *uc = buf;
log("negativ!");
for(i = bytes-1, carry = 1; i>=0; i--) {
uc[i] ^= 0xff;
if(carry)
carry = !++uc[i];
}
}
buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
memset(buf, 0, bytes);
xfree(buf);
}
int
buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
{
/**XXX should be two's-complement */
int len;
unsigned char *bin = (unsigned char *)buffer_get_string(buffer, (unsigned int *)&len);
BN_bin2bn(bin, len, value);
xfree(bin);
return len;
}
/*
* Returns an integer from the buffer (4 bytes, msb first).
*/
unsigned int
buffer_get_int(Buffer *buffer)
{
unsigned char buf[4];
buffer_get(buffer, (char *) buf, 4);
return GET_32BIT(buf);
}
/*
* Stores an integer in the buffer in 4 bytes, msb first.
*/
void
buffer_put_int(Buffer *buffer, unsigned int value)
{
char buf[4];
PUT_32BIT(buf, value);
buffer_append(buffer, buf, 4);
}
/*
* 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.
*/
char *
buffer_get_string(Buffer *buffer, unsigned int *length_ptr)
{
unsigned int len;
char *value;
/* Get the length. */
len = buffer_get_int(buffer);
if (len > 256 * 1024)
fatal("Received packet with bad string length %d", len);
/* Allocate space for the string. Add one byte for a null character. */
value = xmalloc(len + 1);
/* Get the string. */
buffer_get(buffer, value, len);
/* 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;
}
/*
* Stores and arbitrary binary string in the buffer.
*/
void
buffer_put_string(Buffer *buffer, const void *buf, unsigned int len)
{
buffer_put_int(buffer, len);
buffer_append(buffer, buf, len);
}
void
buffer_put_cstring(Buffer *buffer, const char *s)
{
buffer_put_string(buffer, s, strlen(s));
}
/*
* Returns a character from the buffer (0 - 255).
*/
int
buffer_get_char(Buffer *buffer)
{
char ch;
buffer_get(buffer, &ch, 1);
return (unsigned char) ch;
}
/*
* Stores a character in the buffer.
*/
void
buffer_put_char(Buffer *buffer, int value)
{
char ch = value;
buffer_append(buffer, &ch, 1);
}

59
crypto/dist/ssh/bufaux.h vendored Normal file
View File

@ -0,0 +1,59 @@
/* $NetBSD: bufaux.h,v 1.1.1.1 2000/09/28 22:09:46 thorpej 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".
*/
/* from OpenBSD: bufaux.h,v 1.8 2000/09/07 20:27:50 deraadt Exp $ */
#ifndef BUFAUX_H
#define BUFAUX_H
#include "buffer.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.
*/
void buffer_put_bignum(Buffer * buffer, BIGNUM * value);
void buffer_put_bignum2(Buffer * buffer, BIGNUM * value);
/* Retrieves an BIGNUM from the buffer. */
int buffer_get_bignum(Buffer * buffer, BIGNUM * value);
int buffer_get_bignum2(Buffer *buffer, BIGNUM * value);
/* Returns an integer from the buffer (4 bytes, msb first). */
unsigned int buffer_get_int(Buffer * buffer);
/* Stores an integer in the buffer in 4 bytes, msb first. */
void buffer_put_int(Buffer * buffer, unsigned int value);
/* Returns a character from the buffer (0 - 255). */
int buffer_get_char(Buffer * buffer);
/* Stores a character in the buffer. */
void buffer_put_char(Buffer * buffer, int value);
/*
* 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.
*/
char *buffer_get_string(Buffer * buffer, unsigned int *length_ptr);
/* Stores and arbitrary binary string in the buffer. */
void buffer_put_string(Buffer * buffer, const void *buf, unsigned int len);
void buffer_put_cstring(Buffer *buffer, const char *s);
#endif /* BUFAUX_H */

167
crypto/dist/ssh/buffer.c vendored Normal file
View File

@ -0,0 +1,167 @@
/* $NetBSD: buffer.c,v 1.1.1.1 2000/09/28 22:09:47 thorpej 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".
*/
/* from OpenBSD: buffer.c,v 1.8 2000/09/07 20:27:50 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: buffer.c,v 1.1.1.1 2000/09/28 22:09:47 thorpej Exp $");
#endif
#include "includes.h"
#include "xmalloc.h"
#include "buffer.h"
#include "ssh.h"
/* Initializes the buffer structure. */
void
buffer_init(Buffer *buffer)
{
buffer->alloc = 4096;
buffer->buf = xmalloc(buffer->alloc);
buffer->offset = 0;
buffer->end = 0;
}
/* Frees any memory used for the buffer. */
void
buffer_free(Buffer *buffer)
{
memset(buffer->buf, 0, buffer->alloc);
xfree(buffer->buf);
}
/*
* Clears any data from the buffer, making it empty. This does not actually
* zero the memory.
*/
void
buffer_clear(Buffer *buffer)
{
buffer->offset = 0;
buffer->end = 0;
}
/* Appends data to the buffer, expanding it if necessary. */
void
buffer_append(Buffer *buffer, const char *data, unsigned int len)
{
char *cp;
buffer_append_space(buffer, &cp, len);
memcpy(cp, data, len);
}
/*
* 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
buffer_append_space(Buffer *buffer, char **datap, unsigned int 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) {
*datap = buffer->buf + buffer->end;
buffer->end += len;
return;
}
/*
* If the buffer is quite empty, but all data is at the end, move the
* data to the beginning and retry.
*/
if (buffer->offset > buffer->alloc / 2) {
memmove(buffer->buf, buffer->buf + buffer->offset,
buffer->end - buffer->offset);
buffer->end -= buffer->offset;
buffer->offset = 0;
goto restart;
}
/* Increase the size of the buffer and retry. */
buffer->alloc += len + 32768;
buffer->buf = xrealloc(buffer->buf, buffer->alloc);
goto restart;
}
/* Returns the number of bytes of data in the buffer. */
unsigned int
buffer_len(Buffer *buffer)
{
return buffer->end - buffer->offset;
}
/* Gets data from the beginning of the buffer. */
void
buffer_get(Buffer *buffer, char *buf, unsigned int len)
{
if (len > buffer->end - buffer->offset)
fatal("buffer_get: trying to get more bytes than in buffer");
memcpy(buf, buffer->buf + buffer->offset, len);
buffer->offset += len;
}
/* Consumes the given number of bytes from the beginning of the buffer. */
void
buffer_consume(Buffer *buffer, unsigned int bytes)
{
if (bytes > buffer->end - buffer->offset)
fatal("buffer_consume: trying to get more bytes than in buffer");
buffer->offset += bytes;
}
/* Consumes the given number of bytes from the end of the buffer. */
void
buffer_consume_end(Buffer *buffer, unsigned int bytes)
{
if (bytes > buffer->end - buffer->offset)
fatal("buffer_consume_end: trying to get more bytes than in buffer");
buffer->end -= bytes;
}
/* Returns a pointer to the first used byte in the buffer. */
char *
buffer_ptr(Buffer *buffer)
{
return buffer->buf + buffer->offset;
}
/* Dumps the contents of the buffer to stderr. */
void
buffer_dump(Buffer *buffer)
{
int i;
unsigned char *ucp = (unsigned char *) buffer->buf;
for (i = buffer->offset; i < buffer->end; i++)
fprintf(stderr, " %02x", ucp[i]);
fprintf(stderr, "\n");
}

68
crypto/dist/ssh/buffer.h vendored Normal file
View File

@ -0,0 +1,68 @@
/* $NetBSD: buffer.h,v 1.1.1.1 2000/09/28 22:09:47 thorpej 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".
*/
/* from OpenBSD: buffer.h,v 1.6 2000/09/07 20:27:50 deraadt Exp */
#ifndef BUFFER_H
#define BUFFER_H
typedef struct {
char *buf; /* Buffer for data. */
unsigned int alloc; /* Number of bytes allocated for data. */
unsigned int offset; /* Offset of first byte containing data. */
unsigned int end; /* Offset of last byte containing data. */
} Buffer;
/* Initializes the buffer structure. */
void buffer_init(Buffer * buffer);
/* Frees any memory used for the buffer. */
void buffer_free(Buffer * buffer);
/* Clears any data from the buffer, making it empty. This does not actually
zero the memory. */
void buffer_clear(Buffer * buffer);
/* Appends data to the buffer, expanding it if necessary. */
void buffer_append(Buffer * buffer, const char *data, unsigned int len);
/*
* 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 buffer_append_space(Buffer * buffer, char **datap, unsigned int len);
/* Returns the number of bytes of data in the buffer. */
unsigned int buffer_len(Buffer * buffer);
/* Gets data from the beginning of the buffer. */
void buffer_get(Buffer * buffer, char *buf, unsigned int len);
/* Consumes the given number of bytes from the beginning of the buffer. */
void buffer_consume(Buffer * buffer, unsigned int bytes);
/* Consumes the given number of bytes from the end of the buffer. */
void buffer_consume_end(Buffer * buffer, unsigned int bytes);
/* Returns a pointer to the first used byte in the buffer. */
char *buffer_ptr(Buffer * buffer);
/*
* Dumps the contents of the buffer to stderr in hex. This intended for
* debugging purposes only.
*/
void buffer_dump(Buffer * buffer);
#endif /* BUFFER_H */

280
crypto/dist/ssh/canohost.c vendored Normal file
View File

@ -0,0 +1,280 @@
/* $NetBSD: canohost.c,v 1.1.1.1 2000/09/28 22:09:48 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for returning the canonical host name of the remote site.
*
* 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".
*/
/* from OpenBSD: canohost.c,v 1.15 2000/09/07 21:13:37 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: canohost.c,v 1.1.1.1 2000/09/28 22:09:48 thorpej Exp $");
#endif
#include "includes.h"
#include "packet.h"
#include "xmalloc.h"
#include "ssh.h"
/*
* Return the canonical name of the host at the other end of the socket. The
* caller should free the returned string with xfree.
*/
char *
get_remote_hostname(int socket)
{
struct sockaddr_storage from;
int i;
socklen_t fromlen;
struct addrinfo hints, *ai, *aitop;
char name[MAXHOSTNAMELEN];
char ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
NULL, 0, NI_NUMERICHOST) != 0)
fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
NULL, 0, NI_NAMEREQD) == 0) {
/* Got host name. */
name[sizeof(name) - 1] = '\0';
/*
* Convert it to all lowercase (which is expected by the rest
* of this software).
*/
for (i = 0; name[i]; i++)
if (isupper(name[i]))
name[i] = tolower(name[i]);
/*
* Map it back to an IP address and check that the given
* address actually is an address of this host. This is
* necessary because anyone with access to a name server can
* define arbitrary names for an IP address. Mapping from
* name to IP address can be trusted better (but can still be
* fooled if the intruder has access to the name server of
* the domain).
*/
memset(&hints, 0, sizeof(hints));
hints.ai_family = from.ss_family;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
log("reverse mapping checking getaddrinfo for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
strlcpy(name, ntop, sizeof name);
goto check_ip_options;
}
/* Look for the address from the list of addresses. */
for (ai = aitop; ai; ai = ai->ai_next) {
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
(strcmp(ntop, ntop2) == 0))
break;
}
freeaddrinfo(aitop);
/* If we reached the end of the list, the address was not there. */
if (!ai) {
/* Address not found for the host name. */
log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
ntop, name);
strlcpy(name, ntop, sizeof name);
goto check_ip_options;
}
/* Address was found for the host name. We accept the host name. */
} else {
/* Host name not found. Use ascii representation of the address. */
strlcpy(name, ntop, sizeof name);
log("Could not reverse map address %.100s.", name);
}
check_ip_options:
/*
* If IP options are supported, make sure there are none (log and
* disconnect them if any are found). Basically we are worried about
* source routing; it can be used to pretend you are somebody
* (ip-address) you are not. That itself may be "almost acceptable"
* under certain circumstances, but rhosts autentication is useless
* if source routing is accepted. Notice also that if we just dropped
* source routing here, the other side could use IP spoofing to do
* rest of the interaction and could still bypass security. So we
* exit here if we detect any IP options.
*/
/* IP options -- IPv4 only */
if (from.ss_family == AF_INET) {
unsigned char options[200], *ucp;
char text[1024], *cp;
socklen_t option_size;
int ipproto;
struct protoent *ip;
if ((ip = getprotobyname("ip")) != NULL)
ipproto = ip->p_proto;
else
ipproto = IPPROTO_IP;
option_size = sizeof(options);
if (getsockopt(0, ipproto, IP_OPTIONS, (char *) options,
&option_size) >= 0 && option_size != 0) {
cp = text;
/* Note: "text" buffer must be at least 3x as big as options. */
for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
sprintf(cp, " %2.2x", *ucp);
log("Connection from %.100s with IP options:%.800s",
ntop, text);
packet_disconnect("Connection from %.100s with IP options:%.800s",
ntop, text);
}
}
return xstrdup(name);
}
/*
* Return the canonical name of the host in the other side of the current
* connection. The host name is cached, so it is efficient to call this
* several times.
*/
const char *
get_canonical_hostname()
{
static char *canonical_host_name = NULL;
/* Check if we have previously retrieved this same name. */
if (canonical_host_name != NULL)
return canonical_host_name;
/* Get the real hostname if socket; otherwise return UNKNOWN. */
if (packet_connection_is_on_socket())
canonical_host_name = get_remote_hostname(packet_get_connection_in());
else
canonical_host_name = xstrdup("UNKNOWN");
return canonical_host_name;
}
/*
* Returns the IP-address of the remote host as a string. The returned
* string must not be freed.
*/
const char *
get_remote_ipaddr()
{
static char *canonical_host_ip = NULL;
struct sockaddr_storage from;
socklen_t fromlen;
int socket;
char ntop[NI_MAXHOST];
/* Check whether we have chached the name. */
if (canonical_host_ip != NULL)
return canonical_host_ip;
/* If not a socket, return UNKNOWN. */
if (!packet_connection_is_on_socket()) {
canonical_host_ip = xstrdup("UNKNOWN");
return canonical_host_ip;
}
/* Get client socket. */
socket = packet_get_connection_in();
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
/* Get the IP address in ascii. */
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
NULL, 0, NI_NUMERICHOST) != 0)
fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
canonical_host_ip = xstrdup(ntop);
/* Return ip address string. */
return canonical_host_ip;
}
/* Returns the local/remote port for the socket. */
static int
get_sock_port(int sock, int local)
{
struct sockaddr_storage from;
socklen_t fromlen;
char strport[NI_MAXSERV];
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (local) {
if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
error("getsockname failed: %.100s", strerror(errno));
return 0;
}
} else {
if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
fatal_cleanup();
}
}
/* Return port number. */
if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
strport, sizeof(strport), NI_NUMERICSERV) != 0)
fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed");
return atoi(strport);
}
/* Returns remote/local port number for the current connection. */
static int
get_port(int local)
{
/*
* If the connection is not a socket, return 65535. This is
* intentionally chosen to be an unprivileged port number.
*/
if (!packet_connection_is_on_socket())
return 65535;
/* Get socket and return the port number. */
return get_sock_port(packet_get_connection_in(), local);
}
int
get_peer_port(int sock)
{
return get_sock_port(sock, 0);
}
int
get_remote_port()
{
return get_port(0);
}
int
get_local_port()
{
return get_port(1);
}

2313
crypto/dist/ssh/channels.c vendored Normal file

File diff suppressed because it is too large Load Diff

291
crypto/dist/ssh/channels.h vendored Normal file
View File

@ -0,0 +1,291 @@
/* $NetBSD: channels.h,v 1.1.1.1 2000/09/28 22:09:53 thorpej 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.
*/
/* from OpenBSD: channels.h,v 1.20 2000/09/21 11:25:33 markus Exp */
#ifndef CHANNELS_H
#define CHANNELS_H
/* Definitions for channel types. */
#define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */
#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */
#define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */
#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
#define SSH_CHANNEL_AUTH_SOCKET 6 /* authentication socket */
#define SSH_CHANNEL_X11_OPEN 7 /* reading first X11 packet */
#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */
#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */
#define SSH_CHANNEL_LARVAL 10 /* larval session */
#define SSH_CHANNEL_MAX_TYPE 11
/*
* Data structure for channel data. This is iniailized in channel_allocate
* and cleared in channel_free.
*/
struct Channel;
typedef struct Channel Channel;
typedef void channel_callback_fn(int id, void *arg);
typedef int channel_filter_fn(struct Channel *c, char *buf, int len);
struct Channel {
int type; /* channel type/state */
int self; /* my own channel identifier */
int remote_id; /* channel identifier for remote peer */
/* peer can be reached over encrypted connection, via packet-sent */
int istate; /* input from channel (state of receive half) */
int ostate; /* output to channel (state of transmit half) */
int flags; /* close sent/rcvd */
int rfd; /* read fd */
int wfd; /* write fd */
int efd; /* extended fd */
int sock; /* sock fd */
Buffer input; /* data read from socket, to be sent over
* encrypted connection */
Buffer output; /* data received over encrypted connection for
* send on socket */
Buffer extended;
char path[200]; /* path for unix domain sockets, or host name
* for forwards */
int listening_port; /* port being listened for forwards */
int host_port; /* remote port to connect for forwards */
char *remote_name; /* remote hostname */
int remote_window;
int remote_maxpacket;
int local_window;
int local_window_max;
int local_consumed;
int local_maxpacket;
int extended_usage;
char *ctype; /* type */
/* callback */
channel_callback_fn *cb_fn;
void *cb_arg;
int cb_event;
channel_callback_fn *dettach_user;
/* filter */
channel_filter_fn *input_filter;
};
#define CHAN_EXTENDED_IGNORE 0
#define CHAN_EXTENDED_READ 1
#define CHAN_EXTENDED_WRITE 2
/* default window/packet sizes for tcp/x11-fwd-channel */
#define CHAN_SES_WINDOW_DEFAULT (32*1024)
#define CHAN_SES_PACKET_DEFAULT (CHAN_SES_WINDOW_DEFAULT/2)
#define CHAN_TCP_WINDOW_DEFAULT (32*1024)
#define CHAN_TCP_PACKET_DEFAULT (CHAN_TCP_WINDOW_DEFAULT/2)
#define CHAN_X11_WINDOW_DEFAULT (4*1024)
#define CHAN_X11_PACKET_DEFAULT (CHAN_X11_WINDOW_DEFAULT/2)
void channel_set_fds(int id, int rfd, int wfd, int efd, int extusage);
void channel_open(int id);
void channel_request(int id, char *service, int wantconfirm);
void channel_request_start(int id, char *service, int wantconfirm);
void channel_register_callback(int id, int mtype, channel_callback_fn *fn, void *arg);
void channel_register_cleanup(int id, channel_callback_fn *fn);
void channel_register_filter(int id, channel_filter_fn *fn);
void channel_cancel_cleanup(int id);
Channel *channel_lookup(int id);
int
channel_new(char *ctype, int type, int rfd, int wfd, int efd,
int window, int maxpack, int extended_usage, char *remote_name);
void channel_input_channel_request(int type, int plen, void *ctxt);
void channel_input_close(int type, int plen, void *ctxt);
void channel_input_close_confirmation(int type, int plen, void *ctxt);
void channel_input_data(int type, int plen, void *ctxt);
void channel_input_extended_data(int type, int plen, void *ctxt);
void channel_input_ieof(int type, int plen, void *ctxt);
void channel_input_oclose(int type, int plen, void *ctxt);
void channel_input_open_confirmation(int type, int plen, void *ctxt);
void channel_input_open_failure(int type, int plen, void *ctxt);
void channel_input_port_open(int type, int plen, void *ctxt);
void channel_input_window_adjust(int type, int plen, void *ctxt);
void channel_input_open(int type, int plen, void *ctxt);
/* Sets specific protocol options. */
void channel_set_options(int hostname_in_open);
/*
* Allocate a new channel object and set its type and socket. Remote_name
* must have been allocated with xmalloc; this will free it when the channel
* is freed.
*/
int channel_allocate(int type, int sock, char *remote_name);
/* Free the channel and close its socket. */
void channel_free(int channel);
/* Add any bits relevant to channels in select bitmasks. */
void channel_prepare_select(fd_set * readset, fd_set * writeset);
/*
* After select, perform any appropriate operations for channels which have
* events pending.
*/
void channel_after_select(fd_set * readset, fd_set * writeset);
/* If there is data to send to the connection, send some of it now. */
void channel_output_poll(void);
/* Returns true if no channel has too much buffered data. */
int channel_not_very_much_buffered_data(void);
/* This closes any sockets that are listening for connections; this removes
any unix domain sockets. */
void channel_stop_listening(void);
/*
* Closes the sockets of all channels. This is used to close extra file
* descriptors after a fork.
*/
void channel_close_all(void);
/* Returns the maximum file descriptor number used by the channels. */
int channel_max_fd(void);
/* Returns true if there is still an open channel over the connection. */
int channel_still_open(void);
/*
* Returns a string containing a list of all open channels. The list is
* suitable for displaying to the user. It uses crlf instead of newlines.
* The caller should free the string with xfree.
*/
char *channel_open_message(void);
/*
* Initiate forwarding of connections to local port "port" through the secure
* channel to host:port from remote side. This never returns if there was an
* error.
*/
void
channel_request_local_forwarding(u_short port, const char *host,
u_short remote_port, int gateway_ports);
/*
* Initiate forwarding of connections to port "port" on remote host through
* the secure channel to host:port from local side. This never returns if
* there was an error. This registers that open requests for that port are
* permitted.
*/
void
channel_request_remote_forwarding(u_short port, const char *host,
u_short remote_port);
/*
* Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually
* called by the server, because the user could connect to any port anyway,
* and the server has no way to know but to trust the client anyway.
*/
void channel_permit_all_opens(void);
/*
* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
* listening for the port, and sends back a success reply (or disconnect
* message if there was an error). This never returns if there was an error.
*/
void channel_input_port_forward_request(int is_root, int gateway_ports);
/*
* Creates a port for X11 connections, and starts listening for it. Returns
* the display name, or NULL if an error was encountered.
*/
char *x11_create_display(int screen);
/*
* Creates an internet domain socket for listening for X11 connections.
* Returns a suitable value for the DISPLAY variable, or NULL if an error
* occurs.
*/
char *x11_create_display_inet(int screen, int x11_display_offset);
/*
* This is called when SSH_SMSG_X11_OPEN is received. The packet contains
* the remote channel number. We should do whatever we want, and respond
* with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE.
*/
void x11_input_open(int type, int plen, void *ctxt);
/*
* Requests forwarding of X11 connections. This should be called on the
* client only.
*/
void x11_request_forwarding(void);
/*
* Requests forwarding for X11 connections, with authentication spoofing.
* This should be called in the client only.
*/
void
x11_request_forwarding_with_spoofing(int client_session_id,
const char *proto, const char *data);
/* Sends a message to the server to request authentication fd forwarding. */
void auth_request_forwarding(void);
/*
* Returns the name of the forwarded authentication socket. Returns NULL if
* there is no forwarded authentication socket. The returned value points to
* a static buffer.
*/
char *auth_get_socket_name(void);
/*
* This is called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
* This starts forwarding authentication requests.
*/
int auth_input_request_forwarding(struct passwd * pw);
/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
void auth_input_open_request(int type, int plen, void *ctxt);
/* XXX */
int channel_connect_to(const char *host, u_short host_port);
int x11_connect_display(void);
#endif

495
crypto/dist/ssh/cipher.c vendored Normal file
View File

@ -0,0 +1,495 @@
/* $NetBSD: cipher.c,v 1.1.1.1 2000/09/28 22:09:53 thorpej 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) 1999 Niels Provos. All rights reserved.
* Copyright (c) 1999,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.
*/
/* from OpenBSD: cipher.c,v 1.31 2000/09/12 00:38:32 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: cipher.c,v 1.1.1.1 2000/09/28 22:09:53 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "cipher.h"
#include "xmalloc.h"
#include <openssl/md5.h>
/*
* This is used by SSH1:
*
* What kind of triple DES are these 2 routines?
*
* Why is there a redundant initialization vector?
*
* If only iv3 was used, then, this would till effect have been
* outer-cbc. However, there is also a private iv1 == iv2 which
* perhaps makes differential analysis easier. On the other hand, the
* private iv1 probably makes the CRC-32 attack ineffective. This is a
* result of that there is no longer any known iv1 to use when
* choosing the X block.
*/
static void
SSH_3CBC_ENCRYPT(des_key_schedule ks1,
des_key_schedule ks2, des_cblock * iv2,
des_key_schedule ks3, des_cblock * iv3,
unsigned char *dest, unsigned char *src,
unsigned int len)
{
des_cblock iv1;
memcpy(&iv1, iv2, 8);
des_cbc_encrypt(src, dest, len, ks1, &iv1, DES_ENCRYPT);
memcpy(&iv1, dest + len - 8, 8);
des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_DECRYPT);
memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */
des_cbc_encrypt(dest, dest, len, ks3, iv3, DES_ENCRYPT);
memcpy(iv3, dest + len - 8, 8);
}
static void
SSH_3CBC_DECRYPT(des_key_schedule ks1,
des_key_schedule ks2, des_cblock * iv2,
des_key_schedule ks3, des_cblock * iv3,
unsigned char *dest, unsigned char *src,
unsigned int len)
{
des_cblock iv1;
memcpy(&iv1, iv2, 8);
des_cbc_encrypt(src, dest, len, ks3, iv3, DES_DECRYPT);
memcpy(iv3, src + len - 8, 8);
des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_ENCRYPT);
memcpy(iv2, dest + len - 8, 8);
des_cbc_encrypt(dest, dest, len, ks1, &iv1, DES_DECRYPT);
/* memcpy(&iv1, iv2, 8); */
/* Note how iv1 == iv2 on entry and exit. */
}
/*
* SSH1 uses a variation on Blowfish, all bytes must be swapped before
* and after encryption/decryption. Thus the swap_bytes stuff (yuk).
*/
static void
swap_bytes(const unsigned char *src, unsigned char *dst_, int n)
{
/* dst must be properly aligned. */
u_int32_t *dst = (u_int32_t *) dst_;
union {
u_int32_t i;
char c[4];
} t;
/* Process 8 bytes every lap. */
for (n = n / 8; n > 0; n--) {
t.c[3] = *src++;
t.c[2] = *src++;
t.c[1] = *src++;
t.c[0] = *src++;
*dst++ = t.i;
t.c[3] = *src++;
t.c[2] = *src++;
t.c[1] = *src++;
t.c[0] = *src++;
*dst++ = t.i;
}
}
/*
* Names of all encryption algorithms.
* These must match the numbers defined in cipher.h.
*/
static char *cipher_names[] =
{
"none",
"idea",
"des",
"3des",
"tss",
"rc4", /* Alleged RC4 */
"blowfish",
"reserved",
"blowfish-cbc",
"3des-cbc",
"arcfour",
"cast128-cbc"
};
/*
* Returns a bit mask indicating which ciphers are supported by this
* implementation. The bit mask has the corresponding bit set of each
* supported cipher.
*/
unsigned int
cipher_mask1()
{
unsigned int mask = 0;
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
mask |= 1 << SSH_CIPHER_BLOWFISH;
return mask;
}
unsigned int
cipher_mask2()
{
unsigned int mask = 0;
mask |= 1 << SSH_CIPHER_BLOWFISH_CBC;
mask |= 1 << SSH_CIPHER_3DES_CBC;
mask |= 1 << SSH_CIPHER_ARCFOUR;
mask |= 1 << SSH_CIPHER_CAST128_CBC;
return mask;
}
unsigned int
cipher_mask()
{
return cipher_mask1() | cipher_mask2();
}
/* Returns the name of the cipher. */
const char *
cipher_name(int cipher)
{
if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) ||
cipher_names[cipher] == NULL)
fatal("cipher_name: bad cipher name: %d", cipher);
return cipher_names[cipher];
}
/* Returns 1 if the name of the ciphers are valid. */
#define CIPHER_SEP ","
int
ciphers_valid(const char *names)
{
char *ciphers, *cp;
char *p;
int i;
if (names == NULL || strcmp(names, "") == 0)
return 0;
ciphers = cp = xstrdup(names);
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
(p = strsep(&cp, CIPHER_SEP))) {
i = cipher_number(p);
if (i == -1 || !(cipher_mask2() & (1 << i))) {
xfree(ciphers);
return 0;
}
}
xfree(ciphers);
return 1;
}
/*
* Parses the name of the cipher. Returns the number of the corresponding
* cipher, or -1 on error.
*/
int
cipher_number(const char *name)
{
int i;
if (name == NULL)
return -1;
for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++)
if (strcmp(cipher_names[i], name) == 0 &&
(cipher_mask() & (1 << i)))
return i;
return -1;
}
/*
* Selects the cipher, and keys if by computing the MD5 checksum of the
* passphrase and using the resulting 16 bytes as the key.
*/
void
cipher_set_key_string(CipherContext *context, int cipher, const char *passphrase)
{
MD5_CTX md;
unsigned char digest[16];
MD5_Init(&md);
MD5_Update(&md, (const unsigned char *) passphrase, strlen(passphrase));
MD5_Final(digest, &md);
cipher_set_key(context, cipher, digest, 16);
memset(digest, 0, sizeof(digest));
memset(&md, 0, sizeof(md));
}
/* Selects the cipher to use and sets the key. */
void
cipher_set_key(CipherContext *context, int cipher, const unsigned char *key,
int keylen)
{
unsigned char padded[32];
/* Set cipher type. */
context->type = cipher;
/* Get 32 bytes of key data. Pad if necessary. (So that code
below does not need to worry about key size). */
memset(padded, 0, sizeof(padded));
memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded));
/* Initialize the initialization vector. */
switch (cipher) {
case SSH_CIPHER_NONE:
/*
* Has to stay for authfile saving of private key with no
* passphrase
*/
break;
case SSH_CIPHER_3DES:
/*
* Note: the least significant bit of each byte of key is
* parity, and must be ignored by the implementation. 16
* bytes of key are used (first and last keys are the same).
*/
if (keylen < 16)
error("Key length %d is insufficient for 3DES.", keylen);
des_set_key((void *) padded, context->u.des3.key1);
des_set_key((void *) (padded + 8), context->u.des3.key2);
if (keylen <= 16)
des_set_key((void *) padded, context->u.des3.key3);
else
des_set_key((void *) (padded + 16), context->u.des3.key3);
memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2));
memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3));
break;
case SSH_CIPHER_BLOWFISH:
if (keylen < 16)
error("Key length %d is insufficient for blowfish.", keylen);
BF_set_key(&context->u.bf.key, keylen, padded);
memset(context->u.bf.iv, 0, 8);
break;
case SSH_CIPHER_3DES_CBC:
case SSH_CIPHER_BLOWFISH_CBC:
case SSH_CIPHER_ARCFOUR:
case SSH_CIPHER_CAST128_CBC:
fatal("cipher_set_key: illegal cipher: %s", cipher_name(cipher));
break;
default:
fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
}
memset(padded, 0, sizeof(padded));
}
void
cipher_set_key_iv(CipherContext * context, int cipher,
const unsigned char *key, int keylen,
const unsigned char *iv, int ivlen)
{
/* Set cipher type. */
context->type = cipher;
/* Initialize the initialization vector. */
switch (cipher) {
case SSH_CIPHER_NONE:
break;
case SSH_CIPHER_3DES:
case SSH_CIPHER_BLOWFISH:
fatal("cipher_set_key_iv: illegal cipher: %s", cipher_name(cipher));
break;
case SSH_CIPHER_3DES_CBC:
if (keylen < 24)
error("Key length %d is insufficient for 3des-cbc.", keylen);
des_set_key((void *) key, context->u.des3.key1);
des_set_key((void *) (key+8), context->u.des3.key2);
des_set_key((void *) (key+16), context->u.des3.key3);
if (ivlen < 8)
error("IV length %d is insufficient for 3des-cbc.", ivlen);
memcpy(context->u.des3.iv3, (char *)iv, 8);
break;
case SSH_CIPHER_BLOWFISH_CBC:
if (keylen < 16)
error("Key length %d is insufficient for blowfish.", keylen);
if (ivlen < 8)
error("IV length %d is insufficient for blowfish.", ivlen);
BF_set_key(&context->u.bf.key, keylen, (unsigned char *)key);
memcpy(context->u.bf.iv, (char *)iv, 8);
break;
case SSH_CIPHER_ARCFOUR:
if (keylen < 16)
error("Key length %d is insufficient for arcfour.", keylen);
RC4_set_key(&context->u.rc4, keylen, (unsigned char *)key);
break;
case SSH_CIPHER_CAST128_CBC:
if (keylen < 16)
error("Key length %d is insufficient for cast128.", keylen);
if (ivlen < 8)
error("IV length %d is insufficient for cast128.", ivlen);
CAST_set_key(&context->u.cast.key, keylen, (unsigned char *) key);
memcpy(context->u.cast.iv, (char *)iv, 8);
break;
default:
fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
}
}
/* Encrypts data using the cipher. */
void
cipher_encrypt(CipherContext *context, unsigned char *dest,
const unsigned char *src, unsigned int len)
{
if ((len & 7) != 0)
fatal("cipher_encrypt: bad plaintext length %d", len);
switch (context->type) {
case SSH_CIPHER_NONE:
memcpy(dest, src, len);
break;
case SSH_CIPHER_3DES:
SSH_3CBC_ENCRYPT(context->u.des3.key1,
context->u.des3.key2, &context->u.des3.iv2,
context->u.des3.key3, &context->u.des3.iv3,
dest, (unsigned char *) src, len);
break;
case SSH_CIPHER_BLOWFISH:
swap_bytes(src, dest, len);
BF_cbc_encrypt(dest, dest, len,
&context->u.bf.key, context->u.bf.iv,
BF_ENCRYPT);
swap_bytes(dest, dest, len);
break;
case SSH_CIPHER_BLOWFISH_CBC:
BF_cbc_encrypt((void *)src, dest, len,
&context->u.bf.key, context->u.bf.iv,
BF_ENCRYPT);
break;
case SSH_CIPHER_3DES_CBC:
des_ede3_cbc_encrypt(src, dest, len,
context->u.des3.key1, context->u.des3.key2,
context->u.des3.key3, &context->u.des3.iv3, DES_ENCRYPT);
break;
case SSH_CIPHER_ARCFOUR:
RC4(&context->u.rc4, len, (unsigned char *)src, dest);
break;
case SSH_CIPHER_CAST128_CBC:
CAST_cbc_encrypt(src, dest, len,
&context->u.cast.key, context->u.cast.iv, CAST_ENCRYPT);
break;
default:
fatal("cipher_encrypt: unknown cipher: %s", cipher_name(context->type));
}
}
/* Decrypts data using the cipher. */
void
cipher_decrypt(CipherContext *context, unsigned char *dest,
const unsigned char *src, unsigned int len)
{
if ((len & 7) != 0)
fatal("cipher_decrypt: bad ciphertext length %d", len);
switch (context->type) {
case SSH_CIPHER_NONE:
memcpy(dest, src, len);
break;
case SSH_CIPHER_3DES:
SSH_3CBC_DECRYPT(context->u.des3.key1,
context->u.des3.key2, &context->u.des3.iv2,
context->u.des3.key3, &context->u.des3.iv3,
dest, (unsigned char *) src, len);
break;
case SSH_CIPHER_BLOWFISH:
swap_bytes(src, dest, len);
BF_cbc_encrypt((void *) dest, dest, len,
&context->u.bf.key, context->u.bf.iv,
BF_DECRYPT);
swap_bytes(dest, dest, len);
break;
case SSH_CIPHER_BLOWFISH_CBC:
BF_cbc_encrypt((void *) src, dest, len,
&context->u.bf.key, context->u.bf.iv,
BF_DECRYPT);
break;
case SSH_CIPHER_3DES_CBC:
des_ede3_cbc_encrypt(src, dest, len,
context->u.des3.key1, context->u.des3.key2,
context->u.des3.key3, &context->u.des3.iv3, DES_DECRYPT);
break;
case SSH_CIPHER_ARCFOUR:
RC4(&context->u.rc4, len, (unsigned char *)src, dest);
break;
case SSH_CIPHER_CAST128_CBC:
CAST_cbc_encrypt(src, dest, len,
&context->u.cast.key, context->u.cast.iv, CAST_DECRYPT);
break;
default:
fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type));
}
}

116
crypto/dist/ssh/cipher.h vendored Normal file
View File

@ -0,0 +1,116 @@
/* $NetBSD: cipher.h,v 1.1.1.1 2000/09/28 22:09:54 thorpej 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".
*/
/* from OpenBSD: cipher.h,v 1.19 2000/09/07 20:27:50 deraadt Exp */
#ifndef CIPHER_H
#define CIPHER_H
#include <openssl/des.h>
#include <openssl/blowfish.h>
#include <openssl/rc4.h>
#include <openssl/cast.h>
/* Cipher types. New types can be added, but old types should not be removed
for compatibility. The maximum allowed value is 31. */
#define SSH_CIPHER_ILLEGAL -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
/* these ciphers are used in SSH2: */
#define SSH_CIPHER_BLOWFISH_CBC 8
#define SSH_CIPHER_3DES_CBC 9
#define SSH_CIPHER_ARCFOUR 10 /* Alleged RC4 */
#define SSH_CIPHER_CAST128_CBC 11
typedef struct {
unsigned int type;
union {
struct {
des_key_schedule key1;
des_key_schedule key2;
des_cblock iv2;
des_key_schedule key3;
des_cblock iv3;
} des3;
struct {
struct bf_key_st key;
unsigned char iv[8];
} bf;
struct {
CAST_KEY key;
unsigned char iv[8];
} cast;
RC4_KEY rc4;
} u;
} CipherContext;
/*
* Returns a bit mask indicating which ciphers are supported by this
* implementation. The bit mask has the corresponding bit set of each
* supported cipher.
*/
unsigned int cipher_mask(void);
unsigned int cipher_mask1(void);
unsigned int cipher_mask2(void);
/* Returns the name of the cipher. */
const char *cipher_name(int cipher);
/*
* Parses the name of the cipher. Returns the number of the corresponding
* cipher, or -1 on error.
*/
int cipher_number(const char *name);
/* returns 1 if all ciphers are supported (ssh2 only) */
int ciphers_valid(const char *names);
/*
* Selects the cipher to use and sets the key. If for_encryption is true,
* the key is setup for encryption; otherwise it is setup for decryption.
*/
void
cipher_set_key(CipherContext * context, int cipher,
const unsigned char *key, int keylen);
void
cipher_set_key_iv(CipherContext * context, int cipher,
const unsigned char *key, int keylen,
const unsigned char *iv, int ivlen);
/*
* Sets key for the cipher by computing the MD5 checksum of the passphrase,
* and using the resulting 16 bytes as the key.
*/
void
cipher_set_key_string(CipherContext * context, int cipher,
const char *passphrase);
/* Encrypts data using the cipher. */
void
cipher_encrypt(CipherContext * context, unsigned char *dest,
const unsigned char *src, unsigned int len);
/* Decrypts data using the cipher. */
void
cipher_decrypt(CipherContext * context, unsigned char *dest,
const unsigned char *src, unsigned int len);
#endif /* CIPHER_H */

39
crypto/dist/ssh/client.h vendored Normal file
View File

@ -0,0 +1,39 @@
/* $NetBSD: client.h,v 1.1.1.1 2000/09/28 22:09:54 thorpej Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
void client_set_session_ident(int id);

1188
crypto/dist/ssh/clientloop.c vendored Normal file

File diff suppressed because it is too large Load Diff

111
crypto/dist/ssh/compat.c vendored Normal file
View File

@ -0,0 +1,111 @@
/* $NetBSD: compat.c,v 1.1.1.1 2000/09/28 22:10:00 thorpej Exp $ */
/*
* Copyright (c) 1999,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.
*/
/* from OpenBSD: compat.c,v 1.23 2000/09/07 21:13:37 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: compat.c,v 1.1.1.1 2000/09/28 22:10:00 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "packet.h"
#include "xmalloc.h"
#include "compat.h"
int compat13 = 0;
int compat20 = 0;
int datafellows = 0;
void
enable_compat20(void)
{
verbose("Enabling compatibility mode for protocol 2.0");
compat20 = 1;
}
void
enable_compat13(void)
{
verbose("Enabling compatibility mode for protocol 1.3");
compat13 = 1;
}
/* datafellows bug compatibility */
void
compat_datafellows(const char *version)
{
int i;
size_t len;
struct {
char *version;
int bugs;
} check[] = {
{"2.1.0", SSH_BUG_SIGBLOB|SSH_BUG_HMAC},
{"2.0.1", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|SSH_BUG_PUBKEYAUTH|SSH_BUG_X11FWD},
{"2.", SSH_BUG_HMAC|SSH_COMPAT_SESSIONID_ENCODING},
{NULL, 0}
};
/* process table, return first match */
for (i = 0; check[i].version; i++) {
len = strlen(check[i].version);
if (strlen(version) >= len &&
(strncmp(version, check[i].version, len) == 0)) {
verbose("datafellows: %.200s", version);
datafellows = check[i].bugs;
return;
}
}
}
#define SEP ","
int
proto_spec(const char *spec)
{
char *s, *p, *q;
int ret = SSH_PROTO_UNKNOWN;
if (spec == NULL)
return ret;
q = s = xstrdup(spec);
for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) {
switch(atoi(p)) {
case 1:
if (ret == SSH_PROTO_UNKNOWN)
ret |= SSH_PROTO_1_PREFERRED;
ret |= SSH_PROTO_1;
break;
case 2:
ret |= SSH_PROTO_2;
break;
default:
log("ignoring bad proto spec: '%s'.", p);
break;
}
}
xfree(s);
return ret;
}

50
crypto/dist/ssh/compat.h vendored Normal file
View File

@ -0,0 +1,50 @@
/* $NetBSD: compat.h,v 1.1.1.1 2000/09/28 22:10:00 thorpej Exp $ */
/*
* Copyright (c) 1999 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.
*/
/* from OpenBSD: compat.h,v 1.10 2000/09/07 20:27:50 deraadt Exp */
#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 0x01
#define SSH_BUG_PUBKEYAUTH 0x02
#define SSH_BUG_HMAC 0x04
#define SSH_BUG_X11FWD 0x08
#define SSH_COMPAT_SESSIONID_ENCODING 0x10
void enable_compat13(void);
void enable_compat20(void);
void compat_datafellows(const char *s);
int proto_spec(const char *spec);
extern int compat13;
extern int compat20;
extern int datafellows;
#endif

150
crypto/dist/ssh/compress.c vendored Normal file
View File

@ -0,0 +1,150 @@
/* $NetBSD: compress.c,v 1.1.1.1 2000/09/28 22:10:00 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Interface to packet compression for ssh.
*
* 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".
*/
/* from OpenBSD: compress.c,v 1.9 2000/09/07 20:27:50 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: compress.c,v 1.1.1.1 2000/09/28 22:10:00 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "buffer.h"
#include "compress.h"
#include "zlib.h"
static z_stream incoming_stream;
static z_stream outgoing_stream;
/*
* Initializes compression; level is compression level from 1 to 9
* (as in gzip).
*/
void
buffer_compress_init(int level)
{
debug("Enabling compression at level %d.", level);
if (level < 1 || level > 9)
fatal("Bad compression level %d.", level);
inflateInit(&incoming_stream);
deflateInit(&outgoing_stream, level);
}
/* Frees any data structures allocated for compression. */
void
buffer_compress_uninit()
{
debug("compress outgoing: raw data %lu, compressed %lu, factor %.2f",
outgoing_stream.total_in, outgoing_stream.total_out,
outgoing_stream.total_in == 0 ? 0.0 :
(double) outgoing_stream.total_out / outgoing_stream.total_in);
debug("compress incoming: raw data %lu, compressed %lu, factor %.2f",
incoming_stream.total_out, incoming_stream.total_in,
incoming_stream.total_out == 0 ? 0.0 :
(double) incoming_stream.total_in / incoming_stream.total_out);
inflateEnd(&incoming_stream);
deflateEnd(&outgoing_stream);
}
/*
* Compresses the contents of input_buffer into output_buffer. All packets
* compressed using this function will form a single compressed data stream;
* however, data will be flushed at the end of every call so that each
* output_buffer can be decompressed independently (but in the appropriate
* order since they together form a single compression stream) by the
* receiver. This appends the compressed data to the output buffer.
*/
void
buffer_compress(Buffer * input_buffer, Buffer * output_buffer)
{
char buf[4096];
int status;
/* This case is not handled below. */
if (buffer_len(input_buffer) == 0)
return;
/* Input is the contents of the input buffer. */
outgoing_stream.next_in = (unsigned char *) buffer_ptr(input_buffer);
outgoing_stream.avail_in = buffer_len(input_buffer);
/* Loop compressing until deflate() returns with avail_out != 0. */
do {
/* Set up fixed-size output buffer. */
outgoing_stream.next_out = (unsigned char *)buf;
outgoing_stream.avail_out = sizeof(buf);
/* Compress as much data into the buffer as possible. */
status = deflate(&outgoing_stream, Z_PARTIAL_FLUSH);
switch (status) {
case Z_OK:
/* Append compressed data to output_buffer. */
buffer_append(output_buffer, buf,
sizeof(buf) - outgoing_stream.avail_out);
break;
default:
fatal("buffer_compress: deflate returned %d", status);
/* NOTREACHED */
}
} while (outgoing_stream.avail_out == 0);
}
/*
* Uncompresses the contents of input_buffer into output_buffer. All packets
* uncompressed using this function will form a single compressed data
* stream; however, data will be flushed at the end of every call so that
* each output_buffer. This must be called for the same size units that the
* buffer_compress was called, and in the same order that buffers compressed
* with that. This appends the uncompressed data to the output buffer.
*/
void
buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer)
{
char buf[4096];
int status;
incoming_stream.next_in = (unsigned char *) buffer_ptr(input_buffer);
incoming_stream.avail_in = buffer_len(input_buffer);
for (;;) {
/* Set up fixed-size output buffer. */
incoming_stream.next_out = (unsigned char *) buf;
incoming_stream.avail_out = sizeof(buf);
status = inflate(&incoming_stream, Z_PARTIAL_FLUSH);
switch (status) {
case Z_OK:
buffer_append(output_buffer, buf,
sizeof(buf) - incoming_stream.avail_out);
break;
case Z_BUF_ERROR:
/*
* Comments in zlib.h say that we should keep calling
* inflate() until we get an error. This appears to
* be the error that we get.
*/
return;
default:
fatal("buffer_uncompress: inflate returned %d", status);
/* NOTREACHED */
}
}
}

50
crypto/dist/ssh/compress.h vendored Normal file
View File

@ -0,0 +1,50 @@
/* $NetBSD: compress.h,v 1.1.1.1 2000/09/28 22:10:00 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Interface to packet compression for ssh.
*
* 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".
*/
/* from OpenBSD: compress.h,v 1.6 2000/09/07 20:27:50 deraadt Exp */
#ifndef COMPRESS_H
#define COMPRESS_H
/*
* Initializes compression; level is compression level from 1 to 9 (as in
* gzip).
*/
void buffer_compress_init(int level);
/* Frees any data structures allocated by buffer_compress_init. */
void buffer_compress_uninit(void);
/*
* Compresses the contents of input_buffer into output_buffer. All packets
* compressed using this function will form a single compressed data stream;
* however, data will be flushed at the end of every call so that each
* output_buffer can be decompressed independently (but in the appropriate
* order since they together form a single compression stream) by the
* receiver. This appends the compressed data to the output buffer.
*/
void buffer_compress(Buffer * input_buffer, Buffer * output_buffer);
/*
* Uncompresses the contents of input_buffer into output_buffer. All packets
* uncompressed using this function will form a single compressed data
* stream; however, data will be flushed at the end of every call so that
* each output_buffer. This must be called for the same size units that the
* buffer_compress was called, and in the same order that buffers compressed
* with that. This appends the uncompressed data to the output buffer.
*/
void buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer);
#endif /* COMPRESS_H */

119
crypto/dist/ssh/crc32.c vendored Normal file
View File

@ -0,0 +1,119 @@
/* $NetBSD: crc32.c,v 1.1.1.1 2000/09/28 22:10:01 thorpej Exp $ */
/*
* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
* code or tables extracted from it, as desired without restriction.
*
* First, the polynomial itself and its table of feedback terms. The
* polynomial is
* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
*
* Note that we take it "backwards" and put the highest-order term in
* the lowest-order bit. The X^32 term is "implied"; the LSB is the
* X^31 term, etc. The X^0 term (usually shown as "+1") results in
* the MSB being 1
*
* Note that the usual hardware shift register implementation, which
* is what we're using (we're merely optimizing it by doing eight-bit
* chunks at a time) shifts bits into the lowest-order term. In our
* implementation, that means shifting towards the right. Why do we
* do it this way? Because the calculated CRC must be transmitted in
* order from highest-order term to lowest-order term. UARTs transmit
* characters in order from LSB to MSB. By storing the CRC this way
* we hand it to the UART in the order low-byte to high-byte; the UART
* sends each low-bit to hight-bit; and the result is transmission bit
* by bit from highest- to lowest-order term without requiring any bit
* shuffling on our part. Reception works similarly
*
* The feedback terms table consists of 256, 32-bit entries. Notes
*
* The table can be generated at runtime if desired; code to do so
* is shown later. It might not be obvious, but the feedback
* terms simply represent the results of eight shift/xor opera
* tions for all combinations of data and CRC register values
*
* The values must be right-shifted by eight bits by the "updcrc
* logic; the shift must be unsigned (bring in zeroes). On some
* hardware you could probably optimize the shift in assembler by
* using byte-swap instructions
* polynomial $edb88320
*/
/* from OpenBSD: crc32.c,v 1.7 2000/09/07 20:27:51 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: crc32.c,v 1.1.1.1 2000/09/28 22:10:01 thorpej Exp $");
#endif
#include "crc32.h"
static unsigned int crc32_tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
/* Return a 32-bit CRC of the contents of the buffer. */
unsigned int
ssh_crc32(const unsigned char *s, unsigned int len)
{
unsigned int i;
unsigned int crc32val;
crc32val = 0;
for (i = 0; i < len; i ++) {
crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
}
return crc32val;
}

27
crypto/dist/ssh/crc32.h vendored Normal file
View File

@ -0,0 +1,27 @@
/* $NetBSD: crc32.h,v 1.1.1.1 2000/09/28 22:10:01 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1992 Tatu Ylonen, Espoo, Finland
* All rights reserved
* Functions for computing 32-bit CRC.
*
* 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".
*/
/* from OpenBSD: crc32.h,v 1.8 2000/09/07 20:27:51 deraadt Exp */
#ifndef CRC32_H
#define CRC32_H
/*
* This computes a 32 bit CRC of the data in the buffer, and returns the CRC.
* The polynomial used is 0xedb88320.
*/
unsigned int ssh_crc32(const unsigned char *buf, unsigned int len);
#endif /* CRC32_H */

163
crypto/dist/ssh/deattack.c vendored Normal file
View File

@ -0,0 +1,163 @@
/* $NetBSD: deattack.c,v 1.1.1.1 2000/09/28 22:10:01 thorpej Exp $ */
/*
* 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>
*/
/* from OpenBSD: deattack.c,v 1.9 2000/09/07 20:27:51 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: deattack.c,v 1.1.1.1 2000/09/28 22:10:01 thorpej Exp $");
#endif
#include "includes.h"
#include "deattack.h"
#include "ssh.h"
#include "crc32.h"
#include "getput.h"
#include "xmalloc.h"
/* SSH Constants */
#define SSH_MAXBLOCKS (32 * 1024)
#define SSH_BLOCKSIZE (8)
/* Hashing constants */
#define HASH_MINSIZE (8 * 1024)
#define HASH_ENTRYSIZE (2)
#define HASH_FACTOR(x) ((x)*3/2)
#define HASH_UNUSEDCHAR (0xff)
#define HASH_UNUSED (0xffff)
#define HASH_IV (0xfffe)
#define HASH_MINBLOCKS (7*SSH_BLOCKSIZE)
/* Hash function (Input keys are cipher results) */
#define HASH(x) GET_32BIT(x)
#define CMP(a,b) (memcmp(a, b, SSH_BLOCKSIZE))
static void
crc_update(u_int32_t *a, u_int32_t b)
{
b ^= *a;
*a = ssh_crc32((unsigned char *) &b, sizeof(b));
}
/* detect if a block is used in a particular pattern */
static int
check_crc(unsigned char *S, unsigned char *buf, u_int32_t len,
unsigned char *IV)
{
u_int32_t crc;
unsigned char *c;
crc = 0;
if (IV && !CMP(S, IV)) {
crc_update(&crc, 1);
crc_update(&crc, 0);
}
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
if (!CMP(S, c)) {
crc_update(&crc, 1);
crc_update(&crc, 0);
} else {
crc_update(&crc, 0);
crc_update(&crc, 0);
}
}
return (crc == 0);
}
/* Detect a crc32 compensation attack on a packet */
int
detect_attack(unsigned char *buf, u_int32_t len, unsigned char *IV)
{
static u_int16_t *h = (u_int16_t *) NULL;
static u_int16_t n = HASH_MINSIZE / HASH_ENTRYSIZE;
register u_int32_t i, j;
u_int32_t l;
register unsigned char *c;
unsigned char *d;
if (len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
len % SSH_BLOCKSIZE != 0) {
fatal("detect_attack: bad length %d", len);
}
for (l = n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2)
;
if (h == NULL) {
debug("Installing crc compensation attack detector.");
n = l;
h = (u_int16_t *) xmalloc(n * HASH_ENTRYSIZE);
} else {
if (l > n) {
n = l;
h = (u_int16_t *) xrealloc(h, n * HASH_ENTRYSIZE);
}
}
if (len <= HASH_MINBLOCKS) {
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
if (IV && (!CMP(c, IV))) {
if ((check_crc(c, buf, len, IV)))
return (DEATTACK_DETECTED);
else
break;
}
for (d = buf; d < c; d += SSH_BLOCKSIZE) {
if (!CMP(c, d)) {
if ((check_crc(c, buf, len, IV)))
return (DEATTACK_DETECTED);
else
break;
}
}
}
return (DEATTACK_OK);
}
memset(h, HASH_UNUSEDCHAR, n * HASH_ENTRYSIZE);
if (IV)
h[HASH(IV) & (n - 1)] = HASH_IV;
for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) {
for (i = HASH(c) & (n - 1); h[i] != HASH_UNUSED;
i = (i + 1) & (n - 1)) {
if (h[i] == HASH_IV) {
if (!CMP(c, IV)) {
if (check_crc(c, buf, len, IV))
return (DEATTACK_DETECTED);
else
break;
}
} else if (!CMP(c, buf + h[i] * SSH_BLOCKSIZE)) {
if (check_crc(c, buf, len, IV))
return (DEATTACK_DETECTED);
else
break;
}
}
h[i] = j;
}
return (DEATTACK_OK);
}

30
crypto/dist/ssh/deattack.h vendored Normal file
View File

@ -0,0 +1,30 @@
/* $NetBSD: deattack.h,v 1.1.1.1 2000/09/28 22:10:01 thorpej Exp $ */
/*
* Cryptographic attack detector for ssh - Header file
*
* 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>
*/
#ifndef _DEATTACK_H
#define _DEATTACK_H
/* Return codes */
#define DEATTACK_OK 0
#define DEATTACK_DETECTED 1
int detect_attack(unsigned char *buf, u_int32_t len, unsigned char IV[8]);
#endif

82
crypto/dist/ssh/dispatch.c vendored Normal file
View File

@ -0,0 +1,82 @@
/* $NetBSD: dispatch.c,v 1.1.1.1 2000/09/28 22:10:01 thorpej Exp $ */
/*
* 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.
*/
/* from OpenBSD: dispatch.c,v 1.5 2000/09/21 11:25:34 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: dispatch.c,v 1.1.1.1 2000/09/28 22:10:01 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "dispatch.h"
#include "packet.h"
#define DISPATCH_MIN 0
#define DISPATCH_MAX 255
dispatch_fn *dispatch[DISPATCH_MAX];
void
dispatch_protocol_error(int type, int plen, void *ctxt)
{
error("Hm, dispatch protocol error: type %d plen %d", type, plen);
}
void
dispatch_init(dispatch_fn *dflt)
{
int i;
for (i = 0; i < DISPATCH_MAX; i++)
dispatch[i] = dflt;
}
void
dispatch_set(int type, dispatch_fn *fn)
{
dispatch[type] = fn;
}
void
dispatch_run(int mode, int *done, void *ctxt)
{
for (;;) {
int plen;
int type;
if (mode == DISPATCH_BLOCK) {
type = packet_read(&plen);
} else {
type = packet_read_poll(&plen);
if (type == SSH_MSG_NONE)
return;
}
if (type > 0 && type < DISPATCH_MAX && dispatch[type] != NULL)
(*dispatch[type])(type, plen, ctxt);
else
packet_disconnect("protocol error: rcvd type %d", type);
if (done != NULL && *done)
return;
}
}

37
crypto/dist/ssh/dispatch.h vendored Normal file
View File

@ -0,0 +1,37 @@
/* $NetBSD: dispatch.h,v 1.1.1.1 2000/09/28 22:10:01 thorpej Exp $ */
/*
* 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.
*/
enum {
DISPATCH_BLOCK,
DISPATCH_NONBLOCK
};
typedef void dispatch_fn(int type, int plen, void *ctxt);
void dispatch_init(dispatch_fn *dflt);
void dispatch_set(int type, dispatch_fn *fn);
void dispatch_run(int mode, int *done, void *ctxt);
void dispatch_protocol_error(int type, int plen, void *ctxt);

313
crypto/dist/ssh/dsa.c vendored Normal file
View File

@ -0,0 +1,313 @@
/* $NetBSD: dsa.c,v 1.1.1.1 2000/09/28 22:10:02 thorpej Exp $ */
/*
* 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.
*/
/* from OpenBSD: dsa.c,v 1.11 2000/09/07 20:27:51 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: dsa.c,v 1.1.1.1 2000/09/28 22:10:02 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
#include "compat.h"
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/hmac.h>
#include "kex.h"
#include "key.h"
#include "dsa.h"
#include "uuencode.h"
#define INTBLOB_LEN 20
#define SIGBLOB_LEN (2*INTBLOB_LEN)
Key *
dsa_key_from_blob(char *blob, int blen)
{
Buffer b;
char *ktype;
int rlen;
DSA *dsa;
Key *key;
#ifdef DEBUG_DSS
dump_base64(stderr, blob, blen);
#endif
/* fetch & parse DSA/DSS pubkey */
buffer_init(&b);
buffer_append(&b, blob, blen);
ktype = buffer_get_string(&b, NULL);
if (strcmp(KEX_DSS, ktype) != 0) {
error("dsa_key_from_blob: cannot handle type %s", ktype);
buffer_free(&b);
xfree(ktype);
return NULL;
}
key = key_new(KEY_DSA);
dsa = key->dsa;
buffer_get_bignum2(&b, dsa->p);
buffer_get_bignum2(&b, dsa->q);
buffer_get_bignum2(&b, dsa->g);
buffer_get_bignum2(&b, dsa->pub_key);
rlen = buffer_len(&b);
if(rlen != 0)
error("dsa_key_from_blob: remaining bytes in key blob %d", rlen);
buffer_free(&b);
xfree(ktype);
#ifdef DEBUG_DSS
DSA_print_fp(stderr, dsa, 8);
#endif
return key;
}
int
dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
{
Buffer b;
int len;
unsigned char *buf;
if (key == NULL || key->type != KEY_DSA)
return 0;
buffer_init(&b);
buffer_put_cstring(&b, KEX_DSS);
buffer_put_bignum2(&b, key->dsa->p);
buffer_put_bignum2(&b, key->dsa->q);
buffer_put_bignum2(&b, key->dsa->g);
buffer_put_bignum2(&b, key->dsa->pub_key);
len = buffer_len(&b);
buf = xmalloc(len);
memcpy(buf, buffer_ptr(&b), len);
memset(buffer_ptr(&b), 0, len);
buffer_free(&b);
if (lenp != NULL)
*lenp = len;
if (blobp != NULL)
*blobp = buf;
return len;
}
int
dsa_sign(
Key *key,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen)
{
unsigned char *digest;
unsigned char *ret;
DSA_SIG *sig;
EVP_MD *evp_md = EVP_sha1();
EVP_MD_CTX md;
unsigned int rlen;
unsigned int slen;
unsigned int len;
unsigned char sigblob[SIGBLOB_LEN];
Buffer b;
if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
error("dsa_sign: no DSA key");
return -1;
}
digest = xmalloc(evp_md->md_size);
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, data, datalen);
EVP_DigestFinal(&md, digest, NULL);
sig = DSA_do_sign(digest, evp_md->md_size, key->dsa);
if (sig == NULL) {
fatal("dsa_sign: cannot sign");
}
rlen = BN_num_bytes(sig->r);
slen = BN_num_bytes(sig->s);
if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
error("bad sig size %d %d", rlen, slen);
DSA_SIG_free(sig);
return -1;
}
debug("sig size %d %d", rlen, slen);
memset(sigblob, 0, SIGBLOB_LEN);
BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
DSA_SIG_free(sig);
if (datafellows & SSH_BUG_SIGBLOB) {
debug("datafellows");
ret = xmalloc(SIGBLOB_LEN);
memcpy(ret, sigblob, SIGBLOB_LEN);
if (lenp != NULL)
*lenp = SIGBLOB_LEN;
if (sigp != NULL)
*sigp = ret;
} else {
/* ietf-drafts */
buffer_init(&b);
buffer_put_cstring(&b, KEX_DSS);
buffer_put_string(&b, sigblob, SIGBLOB_LEN);
len = buffer_len(&b);
ret = xmalloc(len);
memcpy(ret, buffer_ptr(&b), len);
buffer_free(&b);
if (lenp != NULL)
*lenp = len;
if (sigp != NULL)
*sigp = ret;
}
return 0;
}
int
dsa_verify(
Key *key,
unsigned char *signature, int signaturelen,
unsigned char *data, int datalen)
{
Buffer b;
unsigned char *digest;
DSA_SIG *sig;
EVP_MD *evp_md = EVP_sha1();
EVP_MD_CTX md;
unsigned char *sigblob;
char *txt;
unsigned int len;
int rlen;
int ret;
if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
error("dsa_verify: no DSA key");
return -1;
}
if (!(datafellows & SSH_BUG_SIGBLOB) &&
signaturelen == SIGBLOB_LEN) {
datafellows |= ~SSH_BUG_SIGBLOB;
log("autodetect SSH_BUG_SIGBLOB");
} else if ((datafellows & SSH_BUG_SIGBLOB) &&
signaturelen != SIGBLOB_LEN) {
log("autoremove SSH_BUG_SIGBLOB");
datafellows &= ~SSH_BUG_SIGBLOB;
}
debug("len %d datafellows %d", signaturelen, datafellows);
/* fetch signature */
if (datafellows & SSH_BUG_SIGBLOB) {
sigblob = signature;
len = signaturelen;
} else {
/* ietf-drafts */
char *ktype;
buffer_init(&b);
buffer_append(&b, (char *) signature, signaturelen);
ktype = buffer_get_string(&b, NULL);
if (strcmp(KEX_DSS, ktype) != 0) {
error("dsa_verify: cannot handle type %s", ktype);
buffer_free(&b);
return -1;
}
sigblob = (unsigned char *)buffer_get_string(&b, &len);
rlen = buffer_len(&b);
if(rlen != 0) {
error("remaining bytes in signature %d", rlen);
buffer_free(&b);
return -1;
}
buffer_free(&b);
xfree(ktype);
}
if (len != SIGBLOB_LEN) {
fatal("bad sigbloblen %d != SIGBLOB_LEN", len);
}
/* parse signature */
sig = DSA_SIG_new();
sig->r = BN_new();
sig->s = BN_new();
BN_bin2bn(sigblob, INTBLOB_LEN, sig->r);
BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s);
if (!(datafellows & SSH_BUG_SIGBLOB)) {
memset(sigblob, 0, len);
xfree(sigblob);
}
/* sha1 the data */
digest = xmalloc(evp_md->md_size);
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, data, datalen);
EVP_DigestFinal(&md, digest, NULL);
ret = DSA_do_verify(digest, evp_md->md_size, sig, key->dsa);
memset(digest, 0, evp_md->md_size);
xfree(digest);
DSA_SIG_free(sig);
switch (ret) {
case 1:
txt = "correct";
break;
case 0:
txt = "incorrect";
break;
case -1:
default:
txt = "error";
break;
}
debug("dsa_verify: signature %s", txt);
return ret;
}
Key *
dsa_generate_key(unsigned int bits)
{
DSA *dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
Key *k;
if (dsa == NULL) {
fatal("DSA_generate_parameters failed");
}
if (!DSA_generate_key(dsa)) {
fatal("DSA_generate_keys failed");
}
k = key_new(KEY_EMPTY);
k->type = KEY_DSA;
k->dsa = dsa;
return k;
}

48
crypto/dist/ssh/dsa.h vendored Normal file
View File

@ -0,0 +1,48 @@
/* $NetBSD: dsa.h,v 1.1.1.1 2000/09/28 22:10:02 thorpej Exp $ */
/*
* 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 DSA_H
#define DSA_H
Key *dsa_key_from_blob(char *blob, int blen);
int dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp);
int
dsa_sign(
Key *key,
unsigned char **sigp, int *lenp,
unsigned char *data, int datalen);
int
dsa_verify(
Key *key,
unsigned char *signature, int signaturelen,
unsigned char *data, int datalen);
Key *
dsa_generate_key(unsigned int bits);
#endif

63
crypto/dist/ssh/getput.h vendored Normal file
View File

@ -0,0 +1,63 @@
/* $NetBSD: getput.h,v 1.1.1.1 2000/09/28 22:10:02 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Macros for storing and retrieving data in msb first and lsb first order.
*
* 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".
*/
/* from OpenBSD: getput.h,v 1.5 2000/09/07 20:27:51 deraadt Exp */
#ifndef GETPUT_H
#define GETPUT_H
/*------------ macros for storing/extracting msb first words -------------*/
#define GET_32BIT(cp) (((unsigned long)(unsigned char)(cp)[0] << 24) | \
((unsigned long)(unsigned char)(cp)[1] << 16) | \
((unsigned long)(unsigned char)(cp)[2] << 8) | \
((unsigned long)(unsigned char)(cp)[3]))
#define GET_16BIT(cp) (((unsigned long)(unsigned char)(cp)[0] << 8) | \
((unsigned long)(unsigned char)(cp)[1]))
#define PUT_32BIT(cp, value) do { \
(cp)[0] = (value) >> 24; \
(cp)[1] = (value) >> 16; \
(cp)[2] = (value) >> 8; \
(cp)[3] = (value); } while (0)
#define PUT_16BIT(cp, value) do { \
(cp)[0] = (value) >> 8; \
(cp)[1] = (value); } while (0)
/*------------ macros for storing/extracting lsb first words -------------*/
#define GET_32BIT_LSB_FIRST(cp) \
(((unsigned long)(unsigned char)(cp)[0]) | \
((unsigned long)(unsigned char)(cp)[1] << 8) | \
((unsigned long)(unsigned char)(cp)[2] << 16) | \
((unsigned long)(unsigned char)(cp)[3] << 24))
#define GET_16BIT_LSB_FIRST(cp) \
(((unsigned long)(unsigned char)(cp)[0]) | \
((unsigned long)(unsigned char)(cp)[1] << 8))
#define PUT_32BIT_LSB_FIRST(cp, value) do { \
(cp)[0] = (value); \
(cp)[1] = (value) >> 8; \
(cp)[2] = (value) >> 16; \
(cp)[3] = (value) >> 24; } while (0)
#define PUT_16BIT_LSB_FIRST(cp, value) do { \
(cp)[0] = (value); \
(cp)[1] = (value) >> 8; } while (0)
#endif /* GETPUT_H */

64
crypto/dist/ssh/hmac.c vendored Normal file
View File

@ -0,0 +1,64 @@
/* $NetBSD: hmac.c,v 1.1.1.1 2000/09/28 22:10:02 thorpej Exp $ */
/*
* 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.
*/
/* from OpenBSD: hmac.c,v 1.4 2000/09/07 20:27:51 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: hmac.c,v 1.1.1.1 2000/09/28 22:10:02 thorpej Exp $");
#endif
#include "includes.h"
#include "xmalloc.h"
#include "ssh.h"
#include "getput.h"
#include <openssl/hmac.h>
#include "hmac.h"
unsigned char *
hmac(
EVP_MD *evp_md,
unsigned int seqno,
unsigned char *data, int datalen,
unsigned char *key, int keylen)
{
HMAC_CTX c;
static unsigned char m[EVP_MAX_MD_SIZE];
unsigned char b[4];
if (key == NULL)
fatal("hmac: no key");
HMAC_Init(&c, key, keylen, evp_md);
PUT_32BIT(b, seqno);
HMAC_Update(&c, b, sizeof b);
HMAC_Update(&c, data, datalen);
HMAC_Final(&c, m, NULL);
HMAC_cleanup(&c);
return(m);
}

37
crypto/dist/ssh/hmac.h vendored Normal file
View File

@ -0,0 +1,37 @@
/* $NetBSD: hmac.h,v 1.1.1.1 2000/09/28 22:10:02 thorpej Exp $ */
/*
* 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 HMAC_H
#define HMAC_H
unsigned char *
hmac(
EVP_MD *evp_md,
unsigned int seqno,
unsigned char *data, int datalen,
unsigned char *key, int len);
#endif

224
crypto/dist/ssh/hostfile.c vendored Normal file
View File

@ -0,0 +1,224 @@
/* $NetBSD: hostfile.c,v 1.1.1.1 2000/09/28 22:10:02 thorpej 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 the known hosts files.
*
* 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) 1999,2000 Markus Friedl. All rights reserved.
* Copyright (c) 1999 Niels Provos. 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.
*/
/* from OpenBSD: hostfile.c,v 1.20 2000/09/07 20:27:51 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: hostfile.c,v 1.1.1.1 2000/09/28 22:10:02 thorpej Exp $");
#endif
#include "includes.h"
#include "packet.h"
#include "match.h"
#include "ssh.h"
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include "key.h"
#include "hostfile.h"
/*
* Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the
* pointer over the key. Skips any whitespace at the beginning and at end.
*/
static int
hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
{
unsigned int bits;
char *cp;
/* Skip leading whitespace. */
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
;
bits = key_read(ret, &cp);
if (bits == 0)
return 0;
/* Skip trailing whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
/* Return results. */
*cpp = cp;
*bitsp = bits;
return 1;
}
int
auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
{
Key *k = key_new(KEY_RSA);
int ret = hostfile_read_key(cpp, bitsp, k);
BN_copy(e, k->rsa->e);
BN_copy(n, k->rsa->n);
key_free(k);
return ret;
}
static int
hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum)
{
if (key == NULL || key->type != KEY_RSA || key->rsa == NULL)
return 1;
if (bits != BN_num_bits(key->rsa->n)) {
log("Warning: %s, line %d: keysize mismatch for host %s: "
"actual %d vs. announced %d.",
filename, linenum, host, BN_num_bits(key->rsa->n), bits);
log("Warning: replace %d with %d in %s, line %d.",
bits, BN_num_bits(key->rsa->n), filename, linenum);
}
return 1;
}
/*
* Checks whether the given host (which must be in all lowercase) is already
* in the list of our known hosts. Returns HOST_OK if the host is known and
* has the specified key, HOST_NEW if the host is not known, and HOST_CHANGED
* if the host is known but used to have a different host key.
*/
HostStatus
check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *found)
{
FILE *f;
char line[8192];
int linenum = 0;
unsigned int kbits, hostlen;
char *cp, *cp2;
HostStatus end_return;
if (key == NULL)
fatal("no key to look up");
/* Open the file containing the list of known hosts. */
f = fopen(filename, "r");
if (!f)
return HOST_NEW;
/* Cache the length of the host name. */
hostlen = strlen(host);
/*
* Return value when the loop terminates. This is set to
* HOST_CHANGED if we have seen a different key for the host and have
* not found the proper one.
*/
end_return = HOST_NEW;
/* Go trough the file. */
while (fgets(line, sizeof(line), f)) {
cp = line;
linenum++;
/* Skip any leading whitespace, comments and empty lines. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '#' || *cp == '\n')
continue;
/* Find the end of the host name portion. */
for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)
;
/* Check if the host name matches. */
if (match_hostname(host, cp, (unsigned int) (cp2 - cp)) != 1)
continue;
/* Got a match. Skip host name. */
cp = cp2;
/*
* Extract the key from the line. This will skip any leading
* whitespace. Ignore badly formatted lines.
*/
if (!hostfile_read_key(&cp, &kbits, found))
continue;
if (!hostfile_check_key(kbits, found, host, filename, linenum))
continue;
/* Check if the current key is the same as the given key. */
if (key_equal(key, found)) {
/* Ok, they match. */
fclose(f);
return HOST_OK;
}
/*
* They do not match. We will continue to go through the
* file; however, we note that we will not return that it is
* new.
*/
end_return = HOST_CHANGED;
}
/* Clear variables and close the file. */
fclose(f);
/*
* Return either HOST_NEW or HOST_CHANGED, depending on whether we
* saw a different key for the host.
*/
return end_return;
}
/*
* Appends an entry to the host file. Returns false if the entry could not
* be appended.
*/
int
add_host_to_hostfile(const char *filename, const char *host, Key *key)
{
FILE *f;
int success = 0;
if (key == NULL)
return 1; /* XXX ? */
f = fopen(filename, "a");
if (!f)
return 0;
fprintf(f, "%s ", host);
if (key_write(key, f)) {
success = 1;
} else {
error("add_host_to_hostfile: saving key in %s failed", filename);
}
fprintf(f, "\n");
fclose(f);
return success;
}

36
crypto/dist/ssh/hostfile.h vendored Normal file
View File

@ -0,0 +1,36 @@
/* $NetBSD: hostfile.h,v 1.1.1.1 2000/09/28 22:10:02 thorpej 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 HOSTFILE_H
#define HOSTFILE_H
/*
* Checks whether the given host is already in the list of our known hosts.
* Returns HOST_OK if the host is known and has the specified key, HOST_NEW
* if the host is not known, and HOST_CHANGED if the host is known but used
* to have a different host key. The host must be in all lowercase.
*/
typedef enum {
HOST_OK, HOST_NEW, HOST_CHANGED
} HostStatus;
HostStatus
check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *found);
/*
* Appends an entry to the host file. Returns false if the entry could not
* be appended.
*/
int add_host_to_hostfile(const char *filename, const char *host, Key *key);
#endif

63
crypto/dist/ssh/includes.h vendored Normal file
View File

@ -0,0 +1,63 @@
/* $NetBSD: includes.h,v 1.1.1.1 2000/09/28 22:10:02 thorpej 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 <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/endian.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/un.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netgroup.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <termios.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <time.h>
#include <paths.h>
#include <dirent.h>
#include "version.h"
/*
* Define this to use pipes instead of socketpairs for communicating with the
* client program. Socketpairs do not seem to work on all systems.
*/
#define USE_PIPES 1
#endif /* INCLUDES_H */

478
crypto/dist/ssh/kex.c vendored Normal file
View File

@ -0,0 +1,478 @@
/* $NetBSD: kex.c,v 1.1.1.1 2000/09/28 22:10:03 thorpej Exp $ */
/*
* 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.
*/
/* from OpenBSD: kex.c,v 1.10 2000/09/07 20:27:51 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: kex.c,v 1.1.1.1 2000/09/28 22:10:03 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "ssh2.h"
#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
#include "packet.h"
#include "cipher.h"
#include "compat.h"
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/crypto.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include "kex.h"
#define KEX_COOKIE_LEN 16
Buffer *
kex_init(char *myproposal[PROPOSAL_MAX])
{
int first_kex_packet_follows = 0;
unsigned char cookie[KEX_COOKIE_LEN];
u_int32_t rand = 0;
int i;
Buffer *ki = xmalloc(sizeof(*ki));
for (i = 0; i < KEX_COOKIE_LEN; i++) {
if (i % 4 == 0) {
/* XXXthorpej */
RAND_pseudo_bytes((u_char *)&rand, sizeof(rand));
}
cookie[i] = rand & 0xff;
rand >>= 8;
}
buffer_init(ki);
buffer_append(ki, (char *)cookie, sizeof cookie);
for (i = 0; i < PROPOSAL_MAX; i++)
buffer_put_cstring(ki, myproposal[i]);
buffer_put_char(ki, first_kex_packet_follows);
buffer_put_int(ki, 0); /* uint32 reserved */
return ki;
}
/* send kexinit, parse and save reply */
void
kex_exchange_kexinit(
Buffer *my_kexinit, Buffer *peer_kexint,
char *peer_proposal[PROPOSAL_MAX])
{
int i;
char *ptr;
int plen;
debug("send KEXINIT");
packet_start(SSH2_MSG_KEXINIT);
packet_put_raw(buffer_ptr(my_kexinit), buffer_len(my_kexinit));
packet_send();
packet_write_wait();
debug("done");
/*
* read and save raw KEXINIT payload in buffer. this is used during
* computation of the session_id and the session keys.
*/
debug("wait KEXINIT");
packet_read_expect(&plen, SSH2_MSG_KEXINIT);
ptr = packet_get_raw(&plen);
buffer_append(peer_kexint, ptr, plen);
/* parse packet and save algorithm proposal */
/* skip cookie */
for (i = 0; i < KEX_COOKIE_LEN; i++)
packet_get_char();
/* extract kex init proposal strings */
for (i = 0; i < PROPOSAL_MAX; i++) {
peer_proposal[i] = packet_get_string(NULL);
debug("got kexinit: %s", peer_proposal[i]);
}
/* first kex follow / reserved */
i = packet_get_char();
debug("first kex follow: %d ", i);
i = packet_get_int();
debug("reserved: %d ", i);
packet_done();
debug("done");
}
/* diffie-hellman-group1-sha1 */
int
dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
{
int i;
int n = BN_num_bits(dh_pub);
int bits_set = 0;
/* we only accept g==2 */
if (!BN_is_word(dh->g, 2)) {
log("invalid DH base != 2");
return 0;
}
if (dh_pub->neg) {
log("invalid public DH value: negativ");
return 0;
}
for (i = 0; i <= n; i++)
if (BN_is_bit_set(dh_pub, i))
bits_set++;
debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
/* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1))
return 1;
log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
return 0;
}
DH *
dh_new_group1()
{
static char *group1 =
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
"FFFFFFFF" "FFFFFFFF";
DH *dh;
int ret, tries = 0;
dh = DH_new();
if(dh == NULL)
fatal("DH_new");
ret = BN_hex2bn(&dh->p, group1);
if(ret<0)
fatal("BN_hex2bn");
dh->g = BN_new();
if(dh->g == NULL)
fatal("DH_new g");
BN_set_word(dh->g, 2);
do {
if (DH_generate_key(dh) == 0)
fatal("DH_generate_key");
if (tries++ > 10)
fatal("dh_new_group1: too many bad keys: giving up");
} while (!dh_pub_is_valid(dh, dh->pub_key));
return dh;
}
#ifdef DEBUG_KEX
static void
dump_digest(unsigned char *digest, int len)
{
int i;
for (i = 0; i< len; i++){
fprintf(stderr, "%02x", digest[i]);
if(i%2!=0)
fprintf(stderr, " ");
}
fprintf(stderr, "\n");
}
#endif
unsigned char *
kex_hash(
char *client_version_string,
char *server_version_string,
char *ckexinit, int ckexinitlen,
char *skexinit, int skexinitlen,
char *serverhostkeyblob, int sbloblen,
BIGNUM *client_dh_pub,
BIGNUM *server_dh_pub,
BIGNUM *shared_secret)
{
Buffer b;
static unsigned char digest[EVP_MAX_MD_SIZE];
EVP_MD *evp_md = EVP_sha1();
EVP_MD_CTX md;
buffer_init(&b);
buffer_put_string(&b, client_version_string, strlen(client_version_string));
buffer_put_string(&b, server_version_string, strlen(server_version_string));
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
buffer_put_int(&b, ckexinitlen+1);
buffer_put_char(&b, SSH2_MSG_KEXINIT);
buffer_append(&b, ckexinit, ckexinitlen);
buffer_put_int(&b, skexinitlen+1);
buffer_put_char(&b, SSH2_MSG_KEXINIT);
buffer_append(&b, skexinit, skexinitlen);
buffer_put_string(&b, serverhostkeyblob, sbloblen);
buffer_put_bignum2(&b, client_dh_pub);
buffer_put_bignum2(&b, server_dh_pub);
buffer_put_bignum2(&b, shared_secret);
#ifdef DEBUG_KEX
buffer_dump(&b);
#endif
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
EVP_DigestFinal(&md, digest, NULL);
buffer_free(&b);
#ifdef DEBUG_KEX
dump_digest(digest, evp_md->md_size);
#endif
return digest;
}
static unsigned char *
derive_key(int id, int need, char unsigned *hash, BIGNUM *shared_secret)
{
Buffer b;
EVP_MD *evp_md = EVP_sha1();
EVP_MD_CTX md;
char c = id;
int have;
int mdsz = evp_md->md_size;
unsigned char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz);
buffer_init(&b);
buffer_put_bignum2(&b, shared_secret);
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); /* shared_secret K */
EVP_DigestUpdate(&md, hash, mdsz); /* transport-06 */
EVP_DigestUpdate(&md, &c, 1); /* key id */
EVP_DigestUpdate(&md, hash, mdsz); /* session id */
EVP_DigestFinal(&md, digest, NULL);
/* expand */
for (have = mdsz; need > have; have += mdsz) {
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
EVP_DigestUpdate(&md, hash, mdsz);
EVP_DigestUpdate(&md, digest, have);
EVP_DigestFinal(&md, digest + have, NULL);
}
buffer_free(&b);
#ifdef DEBUG_KEX
fprintf(stderr, "Digest '%c'== ", c);
dump_digest(digest, need);
#endif
return digest;
}
#define NKEYS 6
#define MAX_PROP 20
#define SEP ","
static char *
get_match(char *client, char *server)
{
char *sproposals[MAX_PROP];
char *c, *s, *p, *ret, *cp, *sp;
int i, j, nproposals;
c = cp = xstrdup(client);
s = sp = xstrdup(server);
for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0';
(p = strsep(&sp, SEP)), i++) {
if (i < MAX_PROP)
sproposals[i] = p;
else
break;
}
nproposals = i;
for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0';
(p = strsep(&cp, SEP)), i++) {
for (j = 0; j < nproposals; j++) {
if (strcmp(p, sproposals[j]) == 0) {
ret = xstrdup(p);
xfree(c);
xfree(s);
return ret;
}
}
}
xfree(c);
xfree(s);
return NULL;
}
static void
choose_enc(Enc *enc, char *client, char *server)
{
char *name = get_match(client, server);
if (name == NULL)
fatal("no matching cipher found: client %s server %s", client, server);
enc->type = cipher_number(name);
switch (enc->type) {
case SSH_CIPHER_3DES_CBC:
enc->key_len = 24;
enc->iv_len = 8;
enc->block_size = 8;
break;
case SSH_CIPHER_BLOWFISH_CBC:
case SSH_CIPHER_CAST128_CBC:
enc->key_len = 16;
enc->iv_len = 8;
enc->block_size = 8;
break;
case SSH_CIPHER_ARCFOUR:
enc->key_len = 16;
enc->iv_len = 0;
enc->block_size = 8;
break;
default:
fatal("unsupported cipher %s", name);
}
enc->name = name;
enc->enabled = 0;
enc->iv = NULL;
enc->key = NULL;
}
static void
choose_mac(Mac *mac, char *client, char *server)
{
char *name = get_match(client, server);
if (name == NULL)
fatal("no matching mac found: client %s server %s", client, server);
if (strcmp(name, "hmac-md5") == 0) {
mac->md = EVP_md5();
} else if (strcmp(name, "hmac-sha1") == 0) {
mac->md = EVP_sha1();
} else if (strcmp(name, "hmac-ripemd160@openssh.com") == 0) {
mac->md = EVP_ripemd160();
} else {
fatal("unsupported mac %s", name);
}
mac->name = name;
mac->mac_len = mac->md->md_size;
mac->key_len = (datafellows & SSH_BUG_HMAC) ? 16 : mac->mac_len;
mac->key = NULL;
mac->enabled = 0;
}
static void
choose_comp(Comp *comp, char *client, char *server)
{
char *name = get_match(client, server);
if (name == NULL)
fatal("no matching comp found: client %s server %s", client, server);
if (strcmp(name, "zlib") == 0) {
comp->type = 1;
} else if (strcmp(name, "none") == 0) {
comp->type = 0;
} else {
fatal("unsupported comp %s", name);
}
comp->name = name;
}
static void
choose_kex(Kex *k, char *client, char *server)
{
k->name = get_match(client, server);
if (k->name == NULL)
fatal("no kex alg");
if (strcmp(k->name, KEX_DH1) != 0)
fatal("bad kex alg %s", k->name);
}
static void
choose_hostkeyalg(Kex *k, char *client, char *server)
{
k->hostkeyalg = get_match(client, server);
if (k->hostkeyalg == NULL)
fatal("no hostkey alg");
if (strcmp(k->hostkeyalg, KEX_DSS) != 0)
fatal("bad hostkey alg %s", k->hostkeyalg);
}
Kex *
kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server)
{
int mode;
int ctos; /* direction: if true client-to-server */
int need;
Kex *k;
k = xmalloc(sizeof(*k));
memset(k, 0, sizeof(*k));
k->server = server;
for (mode = 0; mode < MODE_MAX; mode++) {
int nenc, nmac, ncomp;
ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN);
nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
choose_enc (&k->enc [mode], cprop[nenc], sprop[nenc]);
choose_mac (&k->mac [mode], cprop[nmac], sprop[nmac]);
choose_comp(&k->comp[mode], cprop[ncomp], sprop[ncomp]);
debug("kex: %s %s %s %s",
ctos ? "client->server" : "server->client",
k->enc[mode].name,
k->mac[mode].name,
k->comp[mode].name);
}
choose_kex(k, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
choose_hostkeyalg(k, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
need = 0;
for (mode = 0; mode < MODE_MAX; mode++) {
if (need < k->enc[mode].key_len)
need = k->enc[mode].key_len;
if (need < k->enc[mode].iv_len)
need = k->enc[mode].iv_len;
if (need < k->mac[mode].key_len)
need = k->mac[mode].key_len;
}
/* XXX need runden? */
k->we_need = need;
return k;
}
int
kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret)
{
int i;
int mode;
int ctos;
unsigned char *keys[NKEYS];
for (i = 0; i < NKEYS; i++)
keys[i] = derive_key('A'+i, k->we_need, hash, shared_secret);
for (mode = 0; mode < MODE_MAX; mode++) {
ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN);
k->enc[mode].iv = keys[ctos ? 0 : 1];
k->enc[mode].key = keys[ctos ? 2 : 3];
k->mac[mode].key = keys[ctos ? 4 : 5];
}
return 0;
}

114
crypto/dist/ssh/kex.h vendored Normal file
View File

@ -0,0 +1,114 @@
/* $NetBSD: kex.h,v 1.1.1.1 2000/09/28 22:10:03 thorpej Exp $ */
/*
* 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 KEX_H
#define KEX_H
#define KEX_DH1 "diffie-hellman-group1-sha1"
#define KEX_DSS "ssh-dss"
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
};
typedef struct Kex Kex;
typedef struct Mac Mac;
typedef struct Comp Comp;
typedef struct Enc Enc;
struct Enc {
int type;
int enabled;
int block_size;
unsigned char *key;
unsigned char *iv;
int key_len;
int iv_len;
char *name;
};
struct Mac {
EVP_MD *md;
int enabled;
int mac_len;
unsigned char *key;
int key_len;
char *name;
};
struct Comp {
int type;
int enabled;
char *name;
};
struct Kex {
Enc enc [MODE_MAX];
Mac mac [MODE_MAX];
Comp comp[MODE_MAX];
int we_need;
int server;
char *name;
char *hostkeyalg;
};
Buffer *kex_init(char *myproposal[PROPOSAL_MAX]);
void
kex_exchange_kexinit(
Buffer *my_kexinit, Buffer *peer_kexint,
char *peer_proposal[PROPOSAL_MAX]);
Kex *
kex_choose_conf(char *cprop[PROPOSAL_MAX],
char *sprop[PROPOSAL_MAX], int server);
int kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret);
void packet_set_kex(Kex *k);
int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub);
DH *dh_new_group1(void);
unsigned char *
kex_hash(
char *client_version_string,
char *server_version_string,
char *ckexinit, int ckexinitlen,
char *skexinit, int skexinitlen,
char *serverhostkeyblob, int sbloblen,
BIGNUM *client_dh_pub,
BIGNUM *server_dh_pub,
BIGNUM *shared_secret);
#endif

362
crypto/dist/ssh/key.c vendored Normal file
View File

@ -0,0 +1,362 @@
/* $NetBSD: key.c,v 1.1.1.1 2000/09/28 22:10:03 thorpej 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 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.
*/
/*
* read_bignum():
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
*/
/* from OpenBSD: key.c,v 1.11 2000/09/07 20:27:51 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: key.c,v 1.1.1.1 2000/09/28 22:10:03 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/evp.h>
#include "xmalloc.h"
#include "key.h"
#include "dsa.h"
#include "uuencode.h"
#define SSH_DSS "ssh-dss"
Key *
key_new(int type)
{
Key *k;
RSA *rsa;
DSA *dsa;
k = xmalloc(sizeof(*k));
k->type = type;
k->dsa = NULL;
k->rsa = NULL;
switch (k->type) {
case KEY_RSA:
rsa = RSA_new();
rsa->n = BN_new();
rsa->e = BN_new();
k->rsa = rsa;
break;
case KEY_DSA:
dsa = DSA_new();
dsa->p = BN_new();
dsa->q = BN_new();
dsa->g = BN_new();
dsa->pub_key = BN_new();
k->dsa = dsa;
break;
case KEY_EMPTY:
break;
default:
fatal("key_new: bad key type %d", k->type);
break;
}
return k;
}
void
key_free(Key *k)
{
switch (k->type) {
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;
default:
fatal("key_free: bad key type %d", k->type);
break;
}
xfree(k);
}
int
key_equal(Key *a, Key *b)
{
if (a == NULL || b == NULL || a->type != b->type)
return 0;
switch (a->type) {
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;
break;
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;
break;
default:
fatal("key_equal: bad key type %d", a->type);
break;
}
return 0;
}
/*
* Generate key fingerprint in ascii format.
* Based on ideas and code from Bjoern Groenvall <bg@sics.se>
*/
char *
key_fingerprint(Key *k)
{
static char retval[(EVP_MAX_MD_SIZE+1)*3];
unsigned char *blob = NULL;
int len = 0;
int nlen, elen;
switch (k->type) {
case KEY_RSA:
nlen = BN_num_bytes(k->rsa->n);
elen = BN_num_bytes(k->rsa->e);
len = nlen + elen;
blob = xmalloc(len);
BN_bn2bin(k->rsa->n, blob);
BN_bn2bin(k->rsa->e, blob + nlen);
break;
case KEY_DSA:
dsa_make_key_blob(k, &blob, &len);
break;
default:
fatal("key_fingerprint: bad key type %d", k->type);
break;
}
retval[0] = '\0';
if (blob != NULL) {
int i;
unsigned char digest[EVP_MAX_MD_SIZE];
EVP_MD *md = EVP_md5();
EVP_MD_CTX ctx;
EVP_DigestInit(&ctx, md);
EVP_DigestUpdate(&ctx, blob, len);
EVP_DigestFinal(&ctx, digest, NULL);
for(i = 0; i < md->md_size; i++) {
char hex[4];
snprintf(hex, sizeof(hex), "%02x:", digest[i]);
strlcat(retval, hex, sizeof(retval));
}
retval[strlen(retval) - 1] = '\0';
memset(blob, 0, len);
xfree(blob);
}
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) {
error("write_bignum: BN_bn2dec() failed");
return 0;
}
fprintf(f, " %s", buf);
free(buf);
return 1;
}
unsigned int
key_read(Key *ret, char **cpp)
{
Key *k;
unsigned int bits = 0;
char *cp;
int len, n;
unsigned char *blob;
cp = *cpp;
switch(ret->type) {
case KEY_RSA:
/* Get number of bits. */
if (*cp < '0' || *cp > '9')
return 0; /* Bad bit count... */
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
bits = 10 * bits + *cp - '0';
if (bits == 0)
return 0;
*cpp = cp;
/* Get public exponent, public modulus. */
if (!read_bignum(cpp, ret->rsa->e))
return 0;
if (!read_bignum(cpp, ret->rsa->n))
return 0;
break;
case KEY_DSA:
if (strncmp(cp, SSH_DSS " ", 7) != 0)
return 0;
cp += 7;
len = 2*strlen(cp);
blob = xmalloc(len);
n = uudecode(cp, blob, len);
if (n < 0) {
error("key_read: uudecode %s failed", cp);
return 0;
}
k = dsa_key_from_blob(blob, n);
if (k == NULL) {
error("key_read: dsa_key_from_blob %s failed", cp);
return 0;
}
xfree(blob);
if (ret->dsa != NULL)
DSA_free(ret->dsa);
ret->dsa = k->dsa;
k->dsa = NULL;
key_free(k);
bits = BN_num_bits(ret->dsa->p);
/* advance cp: skip whitespace and data */
while (*cp == ' ' || *cp == '\t')
cp++;
while (*cp != '\0' && *cp != ' ' && *cp != '\t')
cp++;
*cpp = cp;
break;
default:
fatal("key_read: bad key type: %d", ret->type);
break;
}
return bits;
}
int
key_write(Key *key, FILE *f)
{
int success = 0;
unsigned int bits = 0;
if (key->type == KEY_RSA && 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 {
error("key_write: failed for RSA key");
}
} else if (key->type == KEY_DSA && key->dsa != NULL) {
int len, n;
unsigned char *blob, *uu;
dsa_make_key_blob(key, &blob, &len);
uu = xmalloc(2*len);
n = uuencode(blob, len, uu, 2*len);
if (n > 0) {
fprintf(f, "%s %s", SSH_DSS, uu);
success = 1;
}
xfree(blob);
xfree(uu);
}
return success;
}
char *
key_type(Key *k)
{
switch (k->type) {
case KEY_RSA:
return "RSA";
break;
case KEY_DSA:
return "DSA";
break;
}
return "unknown";
}
unsigned int
key_size(Key *k){
switch (k->type) {
case KEY_RSA:
return BN_num_bits(k->rsa->n);
break;
case KEY_DSA:
return BN_num_bits(k->dsa->p);
break;
}
return 0;
}

51
crypto/dist/ssh/key.h vendored Normal file
View File

@ -0,0 +1,51 @@
/* $NetBSD: key.h,v 1.1.1.1 2000/09/28 22:10:03 thorpej Exp $ */
/*
* 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 KEY_H
#define KEY_H
typedef struct Key Key;
enum types {
KEY_RSA,
KEY_DSA,
KEY_EMPTY
};
struct Key {
int type;
RSA *rsa;
DSA *dsa;
};
Key *key_new(int type);
void key_free(Key *k);
int key_equal(Key *a, Key *b);
char *key_fingerprint(Key *k);
char *key_type(Key *k);
int key_write(Key *key, FILE *f);
unsigned int key_read(Key *key, char **cpp);
unsigned int key_size(Key *k);
#endif

97
crypto/dist/ssh/log-client.c vendored Normal file
View File

@ -0,0 +1,97 @@
/* $NetBSD: log-client.c,v 1.1.1.1 2000/09/28 22:10:03 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Client-side versions of debug(), log(), etc. These print to stderr.
* This is a stripped down version of log-server.c.
*
* 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.
*/
/* from OpenBSD: log-client.c,v 1.12 2000/09/12 20:53:10 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: log-client.c,v 1.1.1.1 2000/09/28 22:10:03 thorpej Exp $");
#endif
#include "includes.h"
#include "xmalloc.h"
#include "ssh.h"
static LogLevel log_level = SYSLOG_LEVEL_INFO;
/* Initialize the log.
* av0 program name (should be argv[0])
* level logging level
*/
void
log_init(const char *av0, LogLevel level,
SyslogFacility facility, /* ignored */
int on_stderr, /* ignored */
int quiet_mode, /* ignored */
int debug_mode /* ignored */)
{
switch (level) {
case SYSLOG_LEVEL_QUIET:
case SYSLOG_LEVEL_ERROR:
case SYSLOG_LEVEL_FATAL:
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:
/* unchanged */
break;
}
}
#define MSGBUFSIZ 1024
void
do_log(LogLevel level, const char *fmt, va_list args)
{
char msgbuf[MSGBUFSIZ];
if (level > log_level)
return;
if (level >= SYSLOG_LEVEL_DEBUG1)
fprintf(stderr, "debug: ");
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
fprintf(stderr, "%s\r\n", msgbuf);
}

191
crypto/dist/ssh/log-server.c vendored Normal file
View File

@ -0,0 +1,191 @@
/* $NetBSD: log-server.c,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Server-side versions of debug(), log(), etc. These normally send the output
* to the system log.
*
* 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.
*/
/* from OpenBSD: log-server.c,v 1.17 2000/09/12 20:53:10 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: log-server.c,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $");
#endif
#include "includes.h"
#include <syslog.h>
#include "packet.h"
#include "xmalloc.h"
#include "ssh.h"
static LogLevel log_level = SYSLOG_LEVEL_INFO;
static int log_facility = LOG_AUTH;
static int log_on_stderr = 0;
static int log_quiet_mode = 0;
static int log_debug_mode = 0;
/* Initialize the log.
* av0 program name (should be argv[0])
* on_stderr print also on stderr
* level logging level
*/
void
log_init(const char *av0, LogLevel level, SyslogFacility facility,
int on_stderr, int quiet_mode, int debug_mode)
{
switch (level) {
case SYSLOG_LEVEL_QUIET:
case SYSLOG_LEVEL_ERROR:
case SYSLOG_LEVEL_FATAL:
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);
}
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;
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);
}
log_on_stderr = on_stderr;
log_quiet_mode = quiet_mode;
log_debug_mode = debug_mode;
}
#define MSGBUFSIZ 1024
void
do_log(LogLevel level, const char *fmt, va_list args)
{
char msgbuf[MSGBUFSIZ];
char fmtbuf[MSGBUFSIZ];
char *txt = NULL;
int pri = LOG_INFO;
extern char *__progname;
if (level > log_level)
return;
switch (level) {
case SYSLOG_LEVEL_ERROR:
txt = "error";
pri = LOG_ERR;
break;
case SYSLOG_LEVEL_FATAL:
txt = "fatal";
pri = LOG_ERR;
break;
case SYSLOG_LEVEL_INFO:
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", txt, fmt);
vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
} else {
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
}
if (log_on_stderr) {
fprintf(stderr, "%s\n", msgbuf);
} else {
openlog(__progname, LOG_PID, log_facility);
syslog(pri, "%.500s", msgbuf);
closelog();
}
}

247
crypto/dist/ssh/log.c vendored Normal file
View File

@ -0,0 +1,247 @@
/* $NetBSD: log.c,v 1.1.1.1 2000/09/28 22:10:04 thorpej 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".
*/
/*
* Shared versions of debug(), log(), etc.
*
* 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.
*/
/* from OpenBSD: log.c,v 1.10 2000/09/12 20:53:10 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: log.c,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "xmalloc.h"
/* Fatal messages. This function never returns. */
void
fatal(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_FATAL, fmt, args);
va_end(args);
fatal_cleanup();
}
/* Error messages that should be logged. */
void
error(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_ERROR, fmt, args);
va_end(args);
}
/* Log this message (information that usually should go to the log). */
void
log(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_INFO, fmt, args);
va_end(args);
}
/* More detailed messages (information that does not need to go to the log). */
void
verbose(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
va_end(args);
}
/* Debugging messages that should not be logged during normal operation. */
void
debug(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
va_end(args);
}
void
debug2(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
va_end(args);
}
void
debug3(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
va_end(args);
}
/* Fatal cleanup */
struct fatal_cleanup {
struct fatal_cleanup *next;
void (*proc) (void *);
void *context;
};
static struct fatal_cleanup *fatal_cleanups = NULL;
/* Registers a cleanup function to be called by fatal() before exiting. */
void
fatal_add_cleanup(void (*proc) (void *), void *context)
{
struct fatal_cleanup *cu;
cu = xmalloc(sizeof(*cu));
cu->proc = proc;
cu->context = context;
cu->next = fatal_cleanups;
fatal_cleanups = cu;
}
/* Removes a cleanup frunction to be called at fatal(). */
void
fatal_remove_cleanup(void (*proc) (void *context), void *context)
{
struct fatal_cleanup **cup, *cu;
for (cup = &fatal_cleanups; *cup; cup = &cu->next) {
cu = *cup;
if (cu->proc == proc && cu->context == context) {
*cup = cu->next;
xfree(cu);
return;
}
}
fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx\n",
(unsigned long) proc, (unsigned long) context);
}
/* Cleanup and exit */
void
fatal_cleanup(void)
{
struct fatal_cleanup *cu, *next_cu;
static int called = 0;
if (called)
exit(255);
called = 1;
/* Call cleanup functions. */
for (cu = fatal_cleanups; cu; cu = next_cu) {
next_cu = cu->next;
debug("Calling cleanup 0x%lx(0x%lx)",
(unsigned long) cu->proc, (unsigned long) cu->context);
(*cu->proc) (cu->context);
}
exit(255);
}
/* 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 },
{ "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, 0 }
};
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 },
{ "DEBUG1", SYSLOG_LEVEL_DEBUG1 },
{ "DEBUG2", SYSLOG_LEVEL_DEBUG2 },
{ "DEBUG3", SYSLOG_LEVEL_DEBUG3 },
{ NULL, 0 }
};
SyslogFacility
log_facility_number(const 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 (SyslogFacility) - 1;
}
LogLevel
log_level_number(const 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 (LogLevel) - 1;
}

153
crypto/dist/ssh/login.c vendored Normal file
View File

@ -0,0 +1,153 @@
/* $NetBSD: login.c,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* This file performs some of the things login(1) normally does. We cannot
* easily use something like login -p -h host -f user, because there are
* several different logins around, and it is hard to determined what kind of
* login the current system has. Also, we want to be able to execute commands
* on a 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".
*
* Copyright (c) 1999 Theo de Raadt. All rights reserved.
* Copyright (c) 1999 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.
*/
/* from OpenBSD: login.c,v 1.15 2000/09/07 20:27:52 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: login.c,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $");
#endif
#include "includes.h"
#include <util.h>
#include <utmp.h>
#include "ssh.h"
/*
* Returns the time when the user last logged in. Returns 0 if the
* information is not available. This must be called before record_login.
* The host the user logged in from will be returned in buf.
*/
/*
* Returns the time when the user last logged in (or 0 if no previous login
* is found). The name of the host used last time is returned in buf.
*/
unsigned long
get_last_login_time(uid_t uid, const char *logname,
char *buf, unsigned int bufsize)
{
struct lastlog ll;
char *lastlog;
int fd;
lastlog = _PATH_LASTLOG;
buf[0] = '\0';
fd = open(lastlog, O_RDONLY);
if (fd < 0)
return 0;
lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET);
if (read(fd, &ll, sizeof(ll)) != sizeof(ll)) {
close(fd);
return 0;
}
close(fd);
if (bufsize > sizeof(ll.ll_host) + 1)
bufsize = sizeof(ll.ll_host) + 1;
strncpy(buf, ll.ll_host, bufsize - 1);
buf[bufsize - 1] = 0;
return ll.ll_time;
}
/*
* Records that the user has logged in. I these parts of operating systems
* were more standardized.
*/
void
record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid,
const char *host, struct sockaddr * addr)
{
int fd;
struct lastlog ll;
char *lastlog;
struct utmp u;
const char *utmp, *wtmp;
/* Construct an utmp/wtmp entry. */
memset(&u, 0, sizeof(u));
strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line));
u.ut_time = time(NULL);
strncpy(u.ut_name, user, sizeof(u.ut_name));
strncpy(u.ut_host, host, sizeof(u.ut_host));
/* Figure out the file names. */
utmp = _PATH_UTMP;
wtmp = _PATH_WTMP;
login(&u);
lastlog = _PATH_LASTLOG;
/* Update lastlog unless actually recording a logout. */
if (strcmp(user, "") != 0) {
/*
* It is safer to bzero the lastlog structure first because
* some systems might have some extra fields in it (e.g. SGI)
*/
memset(&ll, 0, sizeof(ll));
/* Update lastlog. */
ll.ll_time = time(NULL);
strncpy(ll.ll_line, ttyname + 5, sizeof(ll.ll_line));
strncpy(ll.ll_host, host, sizeof(ll.ll_host));
fd = open(lastlog, O_RDWR);
if (fd >= 0) {
lseek(fd, (off_t) ((long) uid * sizeof(ll)), SEEK_SET);
if (write(fd, &ll, sizeof(ll)) != sizeof(ll))
log("Could not write %.100s: %.100s", lastlog, strerror(errno));
close(fd);
}
}
}
/* Records that the user has logged out. */
void
record_logout(pid_t pid, const char *ttyname)
{
const char *line = ttyname + 5; /* /dev/ttyq8 -> ttyq8 */
if (logout(line))
logwtmp(line, "", "");
}

148
crypto/dist/ssh/match.c vendored Normal file
View File

@ -0,0 +1,148 @@
/* $NetBSD: match.c,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Simple pattern matching, with '*' and '?' as wildcards.
*
* 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".
*/
/* from OpenBSD: match.c,v 1.9 2000/09/07 20:27:52 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: match.c,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "match.h"
/*
* Returns true if the given string matches the pattern (which may contain ?
* and * as wildcards), and zero if it does not match.
*/
int
match_pattern(const char *s, const char *pattern)
{
for (;;) {
/* If at end of pattern, accept if also at end of string. */
if (!*pattern)
return !*s;
if (*pattern == '*') {
/* Skip the asterisk. */
pattern++;
/* If at end of pattern, accept immediately. */
if (!*pattern)
return 1;
/* If next character in pattern is known, optimize. */
if (*pattern != '?' && *pattern != '*') {
/*
* Look instances of the next character in
* pattern, and try to match starting from
* those.
*/
for (; *s; s++)
if (*s == *pattern &&
match_pattern(s + 1, pattern + 1))
return 1;
/* Failed. */
return 0;
}
/*
* Move ahead one character at a time and try to
* match at each position.
*/
for (; *s; s++)
if (match_pattern(s, pattern))
return 1;
/* Failed. */
return 0;
}
/*
* There must be at least one more character in the string.
* If we are at the end, fail.
*/
if (!*s)
return 0;
/* Check if the next character of the string is acceptable. */
if (*pattern != '?' && *pattern != *s)
return 0;
/* Move to the next character, both in string and in pattern. */
s++;
pattern++;
}
/* NOTREACHED */
}
/*
* Tries to match the host name (which must be in all lowercase) against the
* comma-separated sequence of subpatterns (each possibly preceded by ! to
* indicate negation). Returns -1 if negation matches, 1 if there is
* a positive match, 0 if there is no match at all.
*/
int
match_hostname(const char *host, const char *pattern, unsigned int len)
{
char sub[1024];
int negated;
int got_positive;
unsigned int i, subi;
got_positive = 0;
for (i = 0; i < len;) {
/* Check if the subpattern is negated. */
if (pattern[i] == '!') {
negated = 1;
i++;
} else
negated = 0;
/*
* Extract the subpattern up to a comma or end. Convert the
* subpattern to lowercase.
*/
for (subi = 0;
i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
subi++, i++)
sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i];
/* If subpattern too long, return failure (no match). */
if (subi >= sizeof(sub) - 1)
return 0;
/* If the subpattern was terminated by a comma, skip the comma. */
if (i < len && pattern[i] == ',')
i++;
/* Null-terminate the subpattern. */
sub[subi] = '\0';
/* Try to match the subpattern against the host name. */
if (match_pattern(host, sub)) {
if (negated)
return -1; /* Negative */
else
got_positive = 1; /* Positive */
}
}
/*
* Return success if got a positive match. If there was a negative
* match, we have already returned -1 and never get here.
*/
return got_positive;
}

34
crypto/dist/ssh/match.h vendored Normal file
View File

@ -0,0 +1,34 @@
/* $NetBSD: match.h,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* This file contains various auxiliary functions related to multiple
* precision integers.
*
* 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
/*
* Returns true if the given string matches the pattern (which may contain ?
* and * as wildcards), and zero if it does not match.
*/
int match_pattern(const char *s, const char *pattern);
/*
* Tries to match the host name (which must be in all lowercase) against the
* comma-separated sequence of subpatterns (each possibly preceded by ! to
* indicate negation). Returns -1 if negation matches, 1 if there is
* a positive match, 0 if there is no match at all.
*/
int match_hostname(const char *host, const char *pattern, unsigned int len);
#endif

54
crypto/dist/ssh/mpaux.c vendored Normal file
View File

@ -0,0 +1,54 @@
/* $NetBSD: mpaux.c,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* This file contains various auxiliary functions related to multiple
* precision integers.
*
* 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".
*/
/* from OpenBSD: mpaux.c,v 1.14 2000/09/07 20:27:52 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mpaux.c,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $");
#endif
#include "includes.h"
#include <openssl/bn.h>
#include "getput.h"
#include "xmalloc.h"
#include <openssl/md5.h>
#include "mpaux.h"
void
compute_session_id(unsigned char session_id[16],
unsigned char cookie[8],
BIGNUM* host_key_n,
BIGNUM* session_key_n)
{
unsigned int host_key_bytes = BN_num_bytes(host_key_n);
unsigned int session_key_bytes = BN_num_bytes(session_key_n);
unsigned int bytes = host_key_bytes + session_key_bytes;
unsigned char *buf = xmalloc(bytes);
MD5_CTX md;
BN_bn2bin(host_key_n, buf);
BN_bn2bin(session_key_n, buf + host_key_bytes);
MD5_Init(&md);
MD5_Update(&md, buf, bytes);
MD5_Update(&md, cookie, 8);
MD5_Final(session_id, &md);
memset(buf, 0, bytes);
xfree(buf);
}

33
crypto/dist/ssh/mpaux.h vendored Normal file
View File

@ -0,0 +1,33 @@
/* $NetBSD: mpaux.h,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* This file contains various auxiliary functions related to multiple
* precision integers.
*
* 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".
*/
/* from OpenBSD: mpaux.h,v 1.8 2000/09/07 20:27:52 deraadt Exp */
#ifndef MPAUX_H
#define MPAUX_H
/*
* Computes a 16-byte session id in the global variable session_id. The
* session id is computed by concatenating the linearized, msb first
* representations of host_key_n, session_key_n, and the cookie.
*/
void
compute_session_id(unsigned char session_id[16],
unsigned char cookie[8],
BIGNUM * host_key_n,
BIGNUM * session_key_n);
#endif /* MPAUX_H */

46
crypto/dist/ssh/myproposal.h vendored Normal file
View File

@ -0,0 +1,46 @@
/* $NetBSD: myproposal.h,v 1.1.1.1 2000/09/28 22:10:04 thorpej Exp $ */
/*
* 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.
*/
#define KEX_DEFAULT_KEX "diffie-hellman-group1-sha1"
#define KEX_DEFAULT_PK_ALG "ssh-dss"
#define KEX_DEFAULT_ENCRYPT "3des-cbc,blowfish-cbc,arcfour,cast128-cbc"
#define KEX_DEFAULT_MAC "hmac-sha1,hmac-md5,hmac-ripemd160@openssh.com"
#define KEX_DEFAULT_COMP "zlib,none"
#define KEX_DEFAULT_LANG ""
static char *myproposal[PROPOSAL_MAX] = {
KEX_DEFAULT_KEX,
KEX_DEFAULT_PK_ALG,
KEX_DEFAULT_ENCRYPT,
KEX_DEFAULT_ENCRYPT,
KEX_DEFAULT_MAC,
KEX_DEFAULT_MAC,
KEX_DEFAULT_COMP,
KEX_DEFAULT_COMP,
KEX_DEFAULT_LANG,
KEX_DEFAULT_LANG
};

498
crypto/dist/ssh/nchan.c vendored Normal file
View File

@ -0,0 +1,498 @@
/* $NetBSD: nchan.c,v 1.1.1.1 2000/09/28 22:10:05 thorpej Exp $ */
/*
* Copyright (c) 1999 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.
*/
/* from OpenBSD: nchan.c,v 1.19 2000/09/07 20:27:52 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: nchan.c,v 1.1.1.1 2000/09/28 22:10:05 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "buffer.h"
#include "packet.h"
#include "channels.h"
#include "nchan.h"
#include "ssh2.h"
#include "compat.h"
/* functions manipulating channel states */
/*
* EVENTS update channel input/output states execute ACTIONS
*/
/* events concerning the INPUT from socket for channel (istate) */
chan_event_fn *chan_rcvd_oclose = NULL;
chan_event_fn *chan_read_failed = NULL;
chan_event_fn *chan_ibuf_empty = NULL;
/* events concerning the OUTPUT from channel for socket (ostate) */
chan_event_fn *chan_rcvd_ieof = NULL;
chan_event_fn *chan_write_failed = NULL;
chan_event_fn *chan_obuf_empty = NULL;
/*
* ACTIONS: should never update the channel states
*/
static void chan_send_ieof1(Channel *c);
static void chan_send_oclose1(Channel *c);
static void chan_send_close2(Channel *c);
static void chan_send_eof2(Channel *c);
/* channel cleanup */
chan_event_fn *chan_delete_if_full_closed = NULL;
/* helper */
static void chan_shutdown_write(Channel *c);
static void chan_shutdown_read(Channel *c);
/*
* SSH1 specific implementation of event functions
*/
static void
chan_rcvd_oclose1(Channel *c)
{
debug("channel %d: rcvd oclose", c->self);
switch (c->istate) {
case CHAN_INPUT_WAIT_OCLOSE:
debug("channel %d: input wait_oclose -> closed", c->self);
c->istate = CHAN_INPUT_CLOSED;
break;
case CHAN_INPUT_OPEN:
debug("channel %d: input open -> closed", c->self);
chan_shutdown_read(c);
chan_send_ieof1(c);
c->istate = CHAN_INPUT_CLOSED;
break;
case CHAN_INPUT_WAIT_DRAIN:
/* both local read_failed and remote write_failed */
log("channel %d: input drain -> closed", c->self);
chan_send_ieof1(c);
c->istate = CHAN_INPUT_CLOSED;
break;
default:
error("channel %d: protocol error: chan_rcvd_oclose for istate %d",
c->self, c->istate);
return;
}
}
static void
chan_read_failed_12(Channel *c)
{
debug("channel %d: read failed", c->self);
switch (c->istate) {
case CHAN_INPUT_OPEN:
debug("channel %d: input open -> drain", c->self);
chan_shutdown_read(c);
c->istate = CHAN_INPUT_WAIT_DRAIN;
if (buffer_len(&c->input) == 0) {
debug("channel %d: input: no drain shortcut", c->self);
chan_ibuf_empty(c);
}
break;
default:
error("channel %d: internal error: we do not read, but chan_read_failed for istate %d",
c->self, c->istate);
break;
}
}
static void
chan_ibuf_empty1(Channel *c)
{
debug("channel %d: ibuf empty", c->self);
if (buffer_len(&c->input)) {
error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
c->self);
return;
}
switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN:
debug("channel %d: input drain -> wait_oclose", c->self);
chan_send_ieof1(c);
c->istate = CHAN_INPUT_WAIT_OCLOSE;
break;
default:
error("channel %d: internal error: chan_ibuf_empty for istate %d",
c->self, c->istate);
break;
}
}
static void
chan_rcvd_ieof1(Channel *c)
{
debug("channel %d: rcvd ieof", c->self);
if (c->type != SSH_CHANNEL_OPEN) {
debug("channel %d: non-open", c->self);
if (c->istate == CHAN_INPUT_OPEN) {
debug("channel %d: non-open: input open -> wait_oclose", c->self);
chan_shutdown_read(c);
chan_send_ieof1(c);
c->istate = CHAN_INPUT_WAIT_OCLOSE;
} else {
error("channel %d: istate %d != open", c->self, c->istate);
}
if (c->ostate == CHAN_OUTPUT_OPEN) {
debug("channel %d: non-open: output open -> closed", c->self);
chan_send_oclose1(c);
c->ostate = CHAN_OUTPUT_CLOSED;
} else {
error("channel %d: ostate %d != open", c->self, c->ostate);
}
return;
}
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
debug("channel %d: output open -> drain", c->self);
c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
break;
case CHAN_OUTPUT_WAIT_IEOF:
debug("channel %d: output wait_ieof -> closed", c->self);
c->ostate = CHAN_OUTPUT_CLOSED;
break;
default:
error("channel %d: protocol error: chan_rcvd_ieof for ostate %d",
c->self, c->ostate);
break;
}
}
static void
chan_write_failed1(Channel *c)
{
debug("channel %d: write failed", c->self);
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
debug("channel %d: output open -> wait_ieof", c->self);
chan_send_oclose1(c);
c->ostate = CHAN_OUTPUT_WAIT_IEOF;
break;
case CHAN_OUTPUT_WAIT_DRAIN:
debug("channel %d: output wait_drain -> closed", c->self);
chan_send_oclose1(c);
c->ostate = CHAN_OUTPUT_CLOSED;
break;
default:
error("channel %d: internal error: chan_write_failed for ostate %d",
c->self, c->ostate);
break;
}
}
static void
chan_obuf_empty1(Channel *c)
{
debug("channel %d: obuf empty", c->self);
if (buffer_len(&c->output)) {
error("channel %d: internal error: chan_obuf_empty for non empty buffer",
c->self);
return;
}
switch (c->ostate) {
case CHAN_OUTPUT_WAIT_DRAIN:
debug("channel %d: output drain -> closed", c->self);
chan_send_oclose1(c);
c->ostate = CHAN_OUTPUT_CLOSED;
break;
default:
error("channel %d: internal error: chan_obuf_empty for ostate %d",
c->self, c->ostate);
break;
}
}
static void
chan_send_ieof1(Channel *c)
{
debug("channel %d: send ieof", c->self);
switch (c->istate) {
case CHAN_INPUT_OPEN:
case CHAN_INPUT_WAIT_DRAIN:
packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
packet_put_int(c->remote_id);
packet_send();
break;
default:
error("channel %d: internal error: cannot send ieof for istate %d",
c->self, c->istate);
break;
}
}
static void
chan_send_oclose1(Channel *c)
{
debug("channel %d: send oclose", c->self);
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
case CHAN_OUTPUT_WAIT_DRAIN:
chan_shutdown_write(c);
buffer_consume(&c->output, buffer_len(&c->output));
packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
packet_put_int(c->remote_id);
packet_send();
break;
default:
error("channel %d: internal error: cannot send oclose for ostate %d",
c->self, c->ostate);
break;
}
}
static void
chan_delete_if_full_closed1(Channel *c)
{
if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
debug("channel %d: full closed", c->self);
channel_free(c->self);
}
}
/*
* the same for SSH2
*/
static void
chan_rcvd_oclose2(Channel *c)
{
debug("channel %d: rcvd close", c->self);
if (c->flags & CHAN_CLOSE_RCVD)
error("channel %d: protocol error: close rcvd twice", c->self);
c->flags |= CHAN_CLOSE_RCVD;
if (c->type == SSH_CHANNEL_LARVAL) {
/* tear down larval channels immediately */
c->ostate = CHAN_OUTPUT_CLOSED;
c->istate = CHAN_INPUT_CLOSED;
return;
}
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
/* wait until a data from the channel is consumed if a CLOSE is received */
debug("channel %d: output open -> drain", c->self);
c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
break;
}
switch (c->istate) {
case CHAN_INPUT_OPEN:
debug("channel %d: input open -> closed", c->self);
chan_shutdown_read(c);
break;
case CHAN_INPUT_WAIT_DRAIN:
debug("channel %d: input drain -> closed", c->self);
chan_send_eof2(c);
break;
}
c->istate = CHAN_INPUT_CLOSED;
}
static void
chan_ibuf_empty2(Channel *c)
{
debug("channel %d: ibuf empty", c->self);
if (buffer_len(&c->input)) {
error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
c->self);
return;
}
switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN:
debug("channel %d: input drain -> closed", c->self);
if (!(c->flags & CHAN_CLOSE_SENT))
chan_send_eof2(c);
c->istate = CHAN_INPUT_CLOSED;
break;
default:
error("channel %d: internal error: chan_ibuf_empty for istate %d",
c->self, c->istate);
break;
}
}
static void
chan_rcvd_ieof2(Channel *c)
{
debug("channel %d: rcvd eof", c->self);
if (c->ostate == CHAN_OUTPUT_OPEN) {
debug("channel %d: output open -> drain", c->self);
c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
}
}
static void
chan_write_failed2(Channel *c)
{
debug("channel %d: write failed", c->self);
switch (c->ostate) {
case CHAN_OUTPUT_OPEN:
debug("channel %d: output open -> closed", c->self);
chan_shutdown_write(c); /* ?? */
c->ostate = CHAN_OUTPUT_CLOSED;
break;
case CHAN_OUTPUT_WAIT_DRAIN:
debug("channel %d: output drain -> closed", c->self);
chan_shutdown_write(c);
c->ostate = CHAN_OUTPUT_CLOSED;
break;
default:
error("channel %d: internal error: chan_write_failed for ostate %d",
c->self, c->ostate);
break;
}
}
static void
chan_obuf_empty2(Channel *c)
{
debug("channel %d: obuf empty", c->self);
if (buffer_len(&c->output)) {
error("internal error: chan_obuf_empty %d for non empty buffer",
c->self);
return;
}
switch (c->ostate) {
case CHAN_OUTPUT_WAIT_DRAIN:
debug("channel %d: output drain -> closed", c->self);
chan_shutdown_write(c);
c->ostate = CHAN_OUTPUT_CLOSED;
break;
default:
error("channel %d: internal error: chan_obuf_empty for ostate %d",
c->self, c->ostate);
break;
}
}
static void
chan_send_eof2(Channel *c)
{
debug("channel %d: send eof", c->self);
switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN:
packet_start(SSH2_MSG_CHANNEL_EOF);
packet_put_int(c->remote_id);
packet_send();
break;
default:
error("channel %d: internal error: cannot send eof for istate %d",
c->self, c->istate);
break;
}
}
static void
chan_send_close2(Channel *c)
{
debug("channel %d: send close", c->self);
if (c->ostate != CHAN_OUTPUT_CLOSED ||
c->istate != CHAN_INPUT_CLOSED) {
error("channel %d: internal error: cannot send close for istate/ostate %d/%d",
c->self, c->istate, c->ostate);
} else if (c->flags & CHAN_CLOSE_SENT) {
error("channel %d: internal error: already sent close", c->self);
} else {
packet_start(SSH2_MSG_CHANNEL_CLOSE);
packet_put_int(c->remote_id);
packet_send();
c->flags |= CHAN_CLOSE_SENT;
}
}
static void
chan_delete_if_full_closed2(Channel *c)
{
if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
if (!(c->flags & CHAN_CLOSE_SENT)) {
chan_send_close2(c);
}
if ((c->flags & CHAN_CLOSE_SENT) &&
(c->flags & CHAN_CLOSE_RCVD)) {
debug("channel %d: full closed2", c->self);
channel_free(c->self);
}
}
}
/* shared */
void
chan_init_iostates(Channel *c)
{
c->ostate = CHAN_OUTPUT_OPEN;
c->istate = CHAN_INPUT_OPEN;
c->flags = 0;
}
/* init */
void
chan_init(void)
{
if (compat20) {
chan_rcvd_oclose = chan_rcvd_oclose2;
chan_read_failed = chan_read_failed_12;
chan_ibuf_empty = chan_ibuf_empty2;
chan_rcvd_ieof = chan_rcvd_ieof2;
chan_write_failed = chan_write_failed2;
chan_obuf_empty = chan_obuf_empty2;
chan_delete_if_full_closed = chan_delete_if_full_closed2;
} else {
chan_rcvd_oclose = chan_rcvd_oclose1;
chan_read_failed = chan_read_failed_12;
chan_ibuf_empty = chan_ibuf_empty1;
chan_rcvd_ieof = chan_rcvd_ieof1;
chan_write_failed = chan_write_failed1;
chan_obuf_empty = chan_obuf_empty1;
chan_delete_if_full_closed = chan_delete_if_full_closed1;
}
}
/* helper */
static void
chan_shutdown_write(Channel *c)
{
buffer_consume(&c->output, buffer_len(&c->output));
if (compat20 && c->type == SSH_CHANNEL_LARVAL)
return;
/* shutdown failure is allowed if write failed already */
debug("channel %d: close_write", c->self);
if (c->sock != -1) {
if (shutdown(c->sock, SHUT_WR) < 0)
debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s",
c->self, c->sock, strerror(errno));
} else {
if (close(c->wfd) < 0)
log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s",
c->self, c->wfd, strerror(errno));
c->wfd = -1;
}
}
static void
chan_shutdown_read(Channel *c)
{
if (compat20 && c->type == SSH_CHANNEL_LARVAL)
return;
debug("channel %d: close_read", c->self);
if (c->sock != -1) {
if (shutdown(c->sock, SHUT_RD) < 0)
error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s",
c->self, c->sock, c->istate, c->ostate, strerror(errno));
} else {
if (close(c->rfd) < 0)
log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s",
c->self, c->rfd, strerror(errno));
c->rfd = -1;
}
}

93
crypto/dist/ssh/nchan.h vendored Normal file
View File

@ -0,0 +1,93 @@
/* $NetBSD: nchan.h,v 1.1.1.1 2000/09/28 22:10:05 thorpej Exp $ */
/*
* Copyright (c) 1999 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.
*/
/* from OpenBSD: nchan.h,v 1.9 2000/09/07 20:27:52 deraadt Exp */
#ifndef NCHAN_H
#define NCHAN_H
/*
* SSH Protocol 1.5 aka New Channel Protocol
* Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored.
* Written by Markus Friedl in October 1999
*
* Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the
* tear down of channels:
*
* 1.3: strict request-ack-protocol:
* CLOSE ->
* <- CLOSE_CONFIRM
*
* 1.5: uses variations of:
* IEOF ->
* <- OCLOSE
* <- IEOF
* OCLOSE ->
* i.e. both sides have to close the channel
*
* See the debugging output from 'ssh -v' and 'sshd -d' of
* ssh-1.2.27 as an example.
*
*/
/* ssh-proto-1.5 overloads prot-1.3-message-types */
#define SSH_MSG_CHANNEL_INPUT_EOF SSH_MSG_CHANNEL_CLOSE
#define SSH_MSG_CHANNEL_OUTPUT_CLOSE SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
/* possible input states */
#define CHAN_INPUT_OPEN 0x01
#define CHAN_INPUT_WAIT_DRAIN 0x02
#define CHAN_INPUT_WAIT_OCLOSE 0x04
#define CHAN_INPUT_CLOSED 0x08
/* possible output states */
#define CHAN_OUTPUT_OPEN 0x10
#define CHAN_OUTPUT_WAIT_DRAIN 0x20
#define CHAN_OUTPUT_WAIT_IEOF 0x40
#define CHAN_OUTPUT_CLOSED 0x80
#define CHAN_CLOSE_SENT 0x01
#define CHAN_CLOSE_RCVD 0x02
/* Channel EVENTS */
typedef void chan_event_fn(Channel * c);
/* for the input state */
extern chan_event_fn *chan_rcvd_oclose;
extern chan_event_fn *chan_read_failed;
extern chan_event_fn *chan_ibuf_empty;
/* for the output state */
extern chan_event_fn *chan_rcvd_ieof;
extern chan_event_fn *chan_write_failed;
extern chan_event_fn *chan_obuf_empty;
extern chan_event_fn *chan_delete_if_full_closed;
void chan_init_iostates(Channel * c);
void chan_init(void);
#endif

98
crypto/dist/ssh/nchan.ms vendored Normal file
View File

@ -0,0 +1,98 @@
.\" $NetBSD: nchan.ms,v 1.1.1.1 2000/09/28 22:10:06 thorpej Exp $
.\"
.\" Copyright (c) 1999 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.
.\"
.TL
OpenSSH Channel Close Protocol 1.5 Implementation
.SH
Channel Input State Diagram
.PS
reset
l=1
s=1.2
ellipsewid=s*ellipsewid
boxwid=s*boxwid
ellipseht=s*ellipseht
S1: ellipse "INPUT" "OPEN"
move right 2*l from last ellipse.e
S4: ellipse "INPUT" "CLOSED"
move down l from last ellipse.s
S3: ellipse "INPUT" "WAIT" "OCLOSED"
move down l from 1st ellipse.s
S2: ellipse "INPUT" "WAIT" "DRAIN"
arrow "" "rcvd OCLOSE/" "shutdown_read" "send IEOF" from S1.e to S4.w
arrow "ibuf_empty/" "send IEOF" from S2.e to S3.w
arrow from S1.s to S2.n
box invis "read_failed/" "shutdown_read" with .e at last arrow.c
arrow from S3.n to S4.s
box invis "rcvd OCLOSE/" "-" with .w at last arrow.c
ellipse wid .9*ellipsewid ht .9*ellipseht at S4
arrow "start" "" from S1.w+(-0.5,0) to S1.w
arrow from S2.ne to S4.sw
box invis "rcvd OCLOSE/ " with .e at last arrow.c
box invis " send IEOF" with .w at last arrow.c
.PE
.SH
Channel Output State Diagram
.PS
S1: ellipse "OUTPUT" "OPEN"
move right 2*l from last ellipse.e
S3: ellipse "OUTPUT" "WAIT" "IEOF"
move down l from last ellipse.s
S4: ellipse "OUTPUT" "CLOSED"
move down l from 1st ellipse.s
S2: ellipse "OUTPUT" "WAIT" "DRAIN"
arrow "" "write_failed/" "shutdown_write" "send OCLOSE" from S1.e to S3.w
arrow "obuf_empty ||" "write_failed/" "shutdown_write" "send OCLOSE" from S2.e to S4.w
arrow from S1.s to S2.n
box invis "rcvd IEOF/" "-" with .e at last arrow.c
arrow from S3.s to S4.n
box invis "rcvd IEOF/" "-" with .w at last arrow.c
ellipse wid .9*ellipsewid ht .9*ellipseht at S4
arrow "start" "" from S1.w+(-0.5,0) to S1.w
.PE
.SH
Notes
.PP
The input buffer is filled with data from the socket
(the socket represents the local consumer/producer of the
forwarded channel).
The data is then sent over the INPUT-end (transmit-end) of the channel to the
remote peer.
Data sent by the peer is received on the OUTPUT-end (receive-end),
saved in the output buffer and written to the socket.
.PP
If the local protocol instance has forwarded all data on the
INPUT-end of the channel, it sends an IEOF message to the peer.
If the peer receives the IEOF and has consumed all
data he replies with an OCLOSE.
When the local instance receives the OCLOSE
he considers the INPUT-half of the channel closed.
The peer has his OUTOUT-half closed.
.PP
A channel can be deallocated by a protocol instance
if both the INPUT- and the OUTOUT-half on his
side of the channel are closed.
Note that when an instance is unable to consume the
received data, he is permitted to send an OCLOSE
before the matching IEOF is received.

66
crypto/dist/ssh/nchan2.ms vendored Normal file
View File

@ -0,0 +1,66 @@
.\" $NetBSD: nchan2.ms,v 1.1.1.1 2000/09/28 22:10:06 thorpej Exp $
.\"
.TL
OpenSSH Channel Close Protocol 2.0 Implementation
.SH
Channel Input State Diagram
.PS
reset
l=1
s=1.2
ellipsewid=s*ellipsewid
boxwid=s*boxwid
ellipseht=s*ellipseht
S1: ellipse "INPUT" "OPEN"
move right 2*l from last ellipse.e
S3: ellipse invis
move down l from last ellipse.s
S4: ellipse "INPUT" "CLOSED"
move down l from 1st ellipse.s
S2: ellipse "INPUT" "WAIT" "DRAIN"
arrow from S1.e to S4.n
box invis "rcvd CLOSE/" "shutdown_read" with .sw at last arrow.c
arrow "ibuf_empty ||" "rcvd CLOSE/" "send EOF" "" from S2.e to S4.w
arrow from S1.s to S2.n
box invis "read_failed/" "shutdown_read" with .e at last arrow.c
ellipse wid .9*ellipsewid ht .9*ellipseht at S4
arrow "start" "" from S1.w+(-0.5,0) to S1.w
.PE
.SH
Channel Output State Diagram
.PS
S1: ellipse "OUTPUT" "OPEN"
move right 2*l from last ellipse.e
S3: ellipse invis
move down l from last ellipse.s
S4: ellipse "OUTPUT" "CLOSED"
move down l from 1st ellipse.s
S2: ellipse "OUTPUT" "WAIT" "DRAIN"
arrow from S1.e to S4.n
box invis "write_failed/" "shutdown_write" with .sw at last arrow.c
arrow "obuf_empty ||" "write_failed/" "shutdown_write" "" from S2.e to S4.w
arrow from S1.s to S2.n
box invis "rcvd EOF ||" "rcvd CLOSE/" "-" with .e at last arrow.c
ellipse wid .9*ellipsewid ht .9*ellipseht at S4
arrow "start" "" from S1.w+(-0.5,0) to S1.w
.PE
.SH
Notes
.PP
The input buffer is filled with data from the socket
(the socket represents the local consumer/producer of the
forwarded channel).
The data is then sent over the INPUT-end (transmit-end) of the channel to the
remote peer.
Data sent by the peer is received on the OUTPUT-end (receive-end),
saved in the output buffer and written to the socket.
.PP
If the local protocol instance has forwarded all data on the
INPUT-end of the channel, it sends an EOF message to the peer.
.PP
A CLOSE message is sent to the peer if
both the INPUT- and the OUTOUT-half of the local
end of the channel are closed.
.PP
The channel can be deallocated by a protocol instance
if a CLOSE message he been both sent and received.

1318
crypto/dist/ssh/packet.c vendored Normal file

File diff suppressed because it is too large Load Diff

219
crypto/dist/ssh/packet.h vendored Normal file
View File

@ -0,0 +1,219 @@
/* $NetBSD: packet.h,v 1.1.1.1 2000/09/28 22:10:08 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Interface for the packet protocol functions.
*
* 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".
*/
/* from OpenBSD: packet.h,v 1.17 2000/09/07 20:27:52 deraadt Exp */
#ifndef PACKET_H
#define PACKET_H
#include <openssl/bn.h>
/*
* Sets the socket used for communication. Disables encryption until
* packet_set_encryption_key is called. It is permissible that fd_in and
* fd_out are the same descriptor; in that case it is assumed to be a socket.
*/
void packet_set_connection(int fd_in, int fd_out);
/* Puts the connection file descriptors into non-blocking mode. */
void packet_set_nonblocking(void);
/* Returns the file descriptor used for input. */
int packet_get_connection_in(void);
/* Returns the file descriptor used for output. */
int packet_get_connection_out(void);
/*
* Closes the connection (both descriptors) and clears and frees internal
* data structures.
*/
void packet_close(void);
/*
* Causes any further packets to be encrypted using the given key. The same
* key is used for both sending and reception. However, both directions are
* encrypted independently of each other. Cipher types are defined in ssh.h.
*/
void
packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
int cipher_type);
/*
* Sets remote side protocol flags for the current connection. This can be
* called at any time.
*/
void packet_set_protocol_flags(unsigned int flags);
/* Returns the remote protocol flags set earlier by the above function. */
unsigned int packet_get_protocol_flags(void);
/* Enables compression in both directions starting from the next packet. */
void packet_start_compression(int level);
/*
* Informs that the current session is interactive. Sets IP flags for
* optimal performance in interactive use.
*/
void packet_set_interactive(int interactive, int keepalives);
/* Returns true if the current connection is interactive. */
int packet_is_interactive(void);
/* Starts constructing a packet to send. */
void packet_start(int type);
/* Appends a character to the packet data. */
void packet_put_char(int ch);
/* Appends an integer to the packet data. */
void packet_put_int(unsigned int value);
/* Appends an arbitrary precision integer to packet data. */
void packet_put_bignum(BIGNUM * value);
void packet_put_bignum2(BIGNUM * value);
/* Appends a string to packet data. */
void packet_put_string(const char *buf, unsigned int len);
void packet_put_cstring(const char *str);
void packet_put_raw(const char *buf, unsigned int len);
/*
* Finalizes and sends the packet. If the encryption key has been set,
* encrypts the packet before sending.
*/
void packet_send(void);
/* Waits until a packet has been received, and returns its type. */
int packet_read(int *payload_len_ptr);
/*
* Waits until a packet has been received, verifies that its type matches
* that given, and gives a fatal error and exits if there is a mismatch.
*/
void packet_read_expect(int *payload_len_ptr, int type);
/*
* Checks if a full packet is available in the data received so far via
* packet_process_incoming. If so, reads the packet; otherwise returns
* SSH_MSG_NONE. This does not wait for data from the connection.
* SSH_MSG_DISCONNECT is handled specially here. Also, SSH_MSG_IGNORE
* messages are skipped by this function and are never returned to higher
* levels.
*/
int packet_read_poll(int *packet_len_ptr);
/*
* Buffers the given amount of input characters. This is intended to be used
* together with packet_read_poll.
*/
void packet_process_incoming(const char *buf, unsigned int len);
/* Returns a character (0-255) from the packet data. */
unsigned int packet_get_char(void);
/* Returns an integer from the packet data. */
unsigned int packet_get_int(void);
/*
* Returns an arbitrary precision integer from the packet data. The integer
* must have been initialized before this call.
*/
void packet_get_bignum(BIGNUM * value, int *length_ptr);
void packet_get_bignum2(BIGNUM * value, int *length_ptr);
char *packet_get_raw(int *length_ptr);
/*
* Returns a string from the packet data. The string is allocated using
* xmalloc; it is the responsibility of the calling program to free it when
* no longer needed. The length_ptr argument may be NULL, or point to an
* integer into which the length of the string is stored.
*/
char *packet_get_string(unsigned int *length_ptr);
/*
* Logs the error in syslog using LOG_INFO, constructs and sends a disconnect
* packet, closes the connection, and exits. This function never returns.
* The error message should not contain a newline. The total length of the
* message must not exceed 1024 bytes.
*/
void packet_disconnect(const char *fmt,...) __attribute__((format(printf, 1, 2)));
/*
* Sends a diagnostic message to the other side. This message can be sent at
* any time (but not while constructing another message). The message is
* printed immediately, but only if the client is being executed in verbose
* mode. These messages are primarily intended to ease debugging
* authentication problems. The total length of the message must not exceed
* 1024 bytes. This will automatically call packet_write_wait. If the
* remote side protocol flags do not indicate that it supports SSH_MSG_DEBUG,
* this will do nothing.
*/
void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
/* Checks if there is any buffered output, and tries to write some of the output. */
void packet_write_poll(void);
/* Waits until all pending output data has been written. */
void packet_write_wait(void);
/* Returns true if there is buffered data to write to the connection. */
int packet_have_data_to_write(void);
/* Returns true if there is not too much data to write to the connection. */
int packet_not_very_much_data_to_write(void);
/* maximum packet size, requested by client with SSH_CMSG_MAX_PACKET_SIZE */
extern int max_packet_size;
int packet_set_maxsize(int s);
#define packet_get_maxsize() max_packet_size
/* Stores tty modes from the fd into current packet. */
void tty_make_modes(int fd);
/* Parses tty modes for the fd from the current packet. */
void tty_parse_modes(int fd, int *n_bytes_ptr);
#define packet_integrity_check(payload_len, expected_len, type) \
do { \
int _p = (payload_len), _e = (expected_len); \
if (_p != _e) { \
log("Packet integrity error (%d != %d) at %s:%d", \
_p, _e, __FILE__, __LINE__); \
packet_disconnect("Packet integrity error. (%d)", (type)); \
} \
} while (0)
#define packet_done() \
do { \
int _len = packet_remaining(); \
if (_len > 0) { \
log("Packet integrity error (%d bytes remaining) at %s:%d", \
_len ,__FILE__, __LINE__); \
packet_disconnect("Packet integrity error."); \
} \
} while (0)
/* remote host is connected via a socket/ipv4 */
int packet_connection_is_on_socket(void);
int packet_connection_is_ipv4(void);
/* enable SSH2 packet format */
void packet_set_ssh2_format(void);
/* returns remaining payload bytes */
int packet_remaining(void);
#endif /* PACKET_H */

94
crypto/dist/ssh/pathnames.h vendored Normal file
View File

@ -0,0 +1,94 @@
/* $NetBSD: pathnames.h,v 1.1.1.1 2000/09/28 22:10:08 thorpej Exp $ */
#ifndef _PATHNAMES_H
#define _PATHNAMES_H
/* system utility and file paths */
#define _PATH_CP "/bin/cp"
#define _PATH_MOTD "/etc/motd"
#define _PATH_LOGIN "/usr/bin/login"
#define _PATH_RSH "/usr/bin/rsh"
#define _PATH_URANDOM "/dev/urandom"
/* X Window utility and file paths */
#define _PATH_XAUTH "/usr/X11R6/bin/xauth"
#define _PATH_XUNIX_DIR "/tmp/.X11-unix/X"
#define _PATH_SSH_ASKPASS "/usr/X11R6/bin/ssh-askpass"
/* paths specific to the Secure Shell */
/* mk?temp input string for process-specific scratch dir */
#define _PATH_SSH_TMPDIR _PATH_TMP "/ssh-XXXXXXXX"
/* daemon pid file */
#define _PATH_SSH_DAEMON_PID_FILE _PATH_VARRUN "sshd.pid"
/* System-wide files containing host keys of known hosts. */
#define _PATH_SSH_SYSTEM_HOSTFILE "/etc/ssh_known_hosts"
#define _PATH_SSH_SYSTEM_HOSTFILE2 "/etc/ssh_known_hosts2"
/* host keys (should be readable only by root) */
#define _PATH_HOST_KEY_FILE "/etc/ssh_host_key"
#define _PATH_HOST_DSA_KEY_FILE "/etc/ssh_host_dsa_key"
/* client and server config files */
#define _PATH_CLIENT_CONFIG_FILE "/etc/ssh.conf"
#define _PATH_SERVER_CONFIG_FILE "/etc/sshd.conf"
/* the ssh utility itself as called from scp */
#define _PATH_SSH "/usr/bin/ssh"
/* ssh-only version of hosts.equiv */
#define _PATH_SSH_HEQUIV "/etc/shosts.equiv"
/*
* name of the directory in each users home directory containing private
* configuration and data files. May need to change if this secure shell
* implementation becomes incompatible with other implementations.
*/
#define _PATH_SSH_USER_DIR ".ssh"
/*
* Per-user and system-wide ssh "rc" files. These files are executed with
* /bin/sh before starting the shell or command if they exist. They will be
* passed "proto cookie" as arguments if X11 forwarding with spoofing is in
* use. xauth will be run if neither of these exists.
*/
#define _PATH_SSH_USER_RC _PATH_SSH_USER_DIR "/rc"
#define _PATH_SSH_SYSTEM_RC "/etc/sshrc"
/* Per-user file containing host keys of known hosts. */
#define _PATH_SSH_USER_HOSTFILE "~/" _PATH_SSH_USER_DIR "/known_hosts"
#define _PATH_SSH_USER_HOSTFILE2 "~/" _PATH_SSH_USER_DIR "/known_hosts2"
/*
* Name of the default file containing client-side authentication key. This
* file should only be readable by the user him/herself.
*/
#define _PATH_SSH_CLIENT_IDENTITY _PATH_SSH_USER_DIR "/identity"
#define _PATH_SSH_CLIENT_ID_DSA _PATH_SSH_USER_DIR "/id_dsa"
/*
* Configuration and environment files in user's home directory. These
* need not be readable by anyone but the user him/herself, but do not
* contain anything particularly secret. If the user's home directory
* resides on an NFS volume where root is mapped to nobody, this may need
* to be world-readable.
*/
#define _PATH_SSH_USER_CONFFILE _PATH_SSH_USER_DIR "/config"
#define _PATH_SSH_USER_ENVIRONMENT _PATH_SSH_USER_DIR "/environment"
/*
* File containing a list of those rsa keys that permit logging in as this
* user. This file need not be readable by anyone but the user him/herself,
* but does not contain anything particularly secret. If the user's home
* directory resides on an NFS volume where root is mapped to nobody, this
* may need to be world-readable. (This file is read by the daemon which is
* running as root.)
*/
#define _PATH_SSH_USER_PERMITTED_KEYS _PATH_SSH_USER_DIR "/authorized_keys"
#define _PATH_SSH_USER_PERMITTED_KEYS2 _PATH_SSH_USER_DIR "/authorized_keys2"
#endif

283
crypto/dist/ssh/pty.c vendored Normal file
View File

@ -0,0 +1,283 @@
/* $NetBSD: pty.c,v 1.1.1.1 2000/09/28 22:10:08 thorpej Exp $ */
/*
* 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".
*/
/* from OpenBSD: pty.c,v 1.16 2000/09/07 21:13:37 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: pty.c,v 1.1.1.1 2000/09/28 22:10:08 thorpej Exp $");
#endif
#include "includes.h"
#include <util.h>
#include "pty.h"
#include "ssh.h"
/* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */
#if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY)
#undef HAVE_DEV_PTMX
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
/*
* Allocates and opens a pty. Returns 0 if no pty could be allocated, or
* nonzero if a pty was successfully allocated. On success, open file
* descriptors for the pty and tty sides and the name of the tty side are
* returned (the buffer must be able to hold at least 64 characters).
*/
int
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
{
#if defined(HAVE_OPENPTY) || defined(BSD4_4)
/* openpty(3) exists in OSF/1 and some other os'es */
char buf[64];
int i;
i = openpty(ptyfd, ttyfd, buf, NULL, NULL);
if (i < 0) {
error("openpty: %.100s", strerror(errno));
return 0;
}
strlcpy(namebuf, buf, namebuflen); /* possible truncation */
return 1;
#else /* HAVE_OPENPTY */
#ifdef HAVE__GETPTY
/*
* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
* pty's automagically when needed
*/
char *slave;
slave = _getpty(ptyfd, O_RDWR, 0622, 0);
if (slave == NULL) {
error("_getpty: %.100s", strerror(errno));
return 0;
}
strlcpy(namebuf, slave, namebuflen);
/* Open the slave side. */
*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
if (*ttyfd < 0) {
error("%.200s: %.100s", namebuf, strerror(errno));
close(*ptyfd);
return 0;
}
return 1;
#else /* HAVE__GETPTY */
#ifdef 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;
ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if (ptm < 0) {
error("/dev/ptmx: %.100s", strerror(errno));
return 0;
}
if (grantpt(ptm) < 0) {
error("grantpt: %.100s", strerror(errno));
return 0;
}
if (unlockpt(ptm) < 0) {
error("unlockpt: %.100s", strerror(errno));
return 0;
}
pts = ptsname(ptm);
if (pts == NULL)
error("Slave pty side name could not be obtained.");
strlcpy(namebuf, pts, namebuflen);
*ptyfd = ptm;
/* Open the slave side. */
*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
if (*ttyfd < 0) {
error("%.100s: %.100s", namebuf, strerror(errno));
close(*ptyfd);
return 0;
}
/* Push the appropriate streams modules, as described in Solaris pts(7). */
if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
error("ioctl I_PUSH ptem: %.100s", strerror(errno));
if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
error("ioctl I_PUSH ldterm: %.100s", strerror(errno));
if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
error("ioctl I_PUSH ttcompat: %.100s", strerror(errno));
return 1;
#else /* HAVE_DEV_PTMX */
#ifdef HAVE_DEV_PTS_AND_PTC
/* AIX-style pty code. */
const char *name;
*ptyfd = open("/dev/ptc", O_RDWR | O_NOCTTY);
if (*ptyfd < 0) {
error("Could not open /dev/ptc: %.100s", strerror(errno));
return 0;
}
name = ttyname(*ptyfd);
if (!name)
fatal("Open of /dev/ptc returns device for which ttyname fails.");
strlcpy(namebuf, name, namebuflen);
*ttyfd = open(name, O_RDWR | O_NOCTTY);
if (*ttyfd < 0) {
error("Could not open pty slave side %.100s: %.100s",
name, strerror(errno));
close(*ptyfd);
return 0;
}
return 1;
#else /* HAVE_DEV_PTS_AND_PTC */
/* BSD-style pty code. */
char buf[64];
int i;
const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char *ptyminors = "0123456789abcdef";
int num_minors = strlen(ptyminors);
int num_ptys = strlen(ptymajors) * num_minors;
for (i = 0; i < num_ptys; i++) {
snprintf(buf, sizeof buf, "/dev/pty%c%c", ptymajors[i / num_minors],
ptyminors[i % num_minors]);
*ptyfd = open(buf, O_RDWR | O_NOCTTY);
if (*ptyfd < 0)
continue;
snprintf(namebuf, namebuflen, _PATH_TTY "%c%c",
ptymajors[i / num_minors], ptyminors[i % num_minors]);
/* Open the slave side. */
*ttyfd = open(namebuf, O_RDWR | O_NOCTTY);
if (*ttyfd < 0) {
error("%.100s: %.100s", namebuf, strerror(errno));
close(*ptyfd);
return 0;
}
return 1;
}
return 0;
#endif /* HAVE_DEV_PTS_AND_PTC */
#endif /* HAVE_DEV_PTMX */
#endif /* HAVE__GETPTY */
#endif /* HAVE_OPENPTY */
}
/* Releases the tty. Its ownership is returned to root, and permissions to 0666. */
void
pty_release(const char *ttyname)
{
if (chown(ttyname, (uid_t) 0, (gid_t) 0) < 0)
error("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
if (chmod(ttyname, (mode_t) 0666) < 0)
error("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
}
/* Makes the tty the processes controlling tty and sets it to sane modes. */
void
pty_make_controlling_tty(int *ttyfd, const char *ttyname)
{
int fd;
/* First disconnect from the old controlling tty. */
#ifdef TIOCNOTTY
fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
if (fd >= 0) {
(void) ioctl(fd, TIOCNOTTY, NULL);
close(fd);
}
#endif /* TIOCNOTTY */
if (setsid() < 0)
error("setsid: %.100s", strerror(errno));
/*
* Verify that we are successfully disconnected from the controlling
* tty.
*/
fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
if (fd >= 0) {
error("Failed to disconnect from controlling tty.");
close(fd);
}
/* Make it our controlling tty. */
#ifdef TIOCSCTTY
debug("Setting controlling tty using TIOCSCTTY.");
/*
* We ignore errors from this, because HPSUX defines TIOCSCTTY, but
* returns EINVAL with these arguments, and there is absolutely no
* documentation.
*/
ioctl(*ttyfd, TIOCSCTTY, NULL);
#endif /* TIOCSCTTY */
fd = open(ttyname, O_RDWR);
if (fd < 0)
error("%.100s: %.100s", ttyname, strerror(errno));
else
close(fd);
/* Verify that we now have a controlling tty. */
fd = open(_PATH_TTY, O_WRONLY);
if (fd < 0)
error("open " _PATH_TTY " failed - could not set controlling tty: %.100s",
strerror(errno));
else {
close(fd);
}
}
/* Changes the window size associated with the pty. */
void
pty_change_window_size(int ptyfd, int row, int col,
int xpixel, int ypixel)
{
struct winsize w;
w.ws_row = row;
w.ws_col = col;
w.ws_xpixel = xpixel;
w.ws_ypixel = ypixel;
(void) ioctl(ptyfd, TIOCSWINSZ, &w);
}
void
pty_setowner(struct passwd *pw, const char *ttyname)
{
struct group *grp;
gid_t gid;
mode_t mode;
/* Determine the group to make the owner of the tty. */
grp = getgrnam("tty");
if (grp) {
gid = grp->gr_gid;
mode = S_IRUSR | S_IWUSR | S_IWGRP;
} else {
gid = pw->pw_gid;
mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
}
/* Change ownership of the tty. */
if (chown(ttyname, pw->pw_uid, gid) < 0)
fatal("chown(%.100s, %d, %d) failed: %.100s",
ttyname, pw->pw_uid, gid, strerror(errno));
if (chmod(ttyname, mode) < 0)
fatal("chmod(%.100s, 0%o) failed: %.100s",
ttyname, mode, strerror(errno));
}

49
crypto/dist/ssh/pty.h vendored Normal file
View File

@ -0,0 +1,49 @@
/* $NetBSD: pty.h,v 1.1.1.1 2000/09/28 22:10:08 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for 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".
*/
/* from OpenBSD: pty.h,v 1.8 2000/09/07 20:27:52 deraadt Exp */
#ifndef PTY_H
#define PTY_H
/*
* Allocates and opens a pty. Returns 0 if no pty could be allocated, or
* nonzero if a pty was successfully allocated. On success, open file
* descriptors for the pty and tty sides and the name of the tty side are
* returned (the buffer must be able to hold at least 64 characters).
*/
int pty_allocate(int *ptyfd, int *ttyfd, char *ttyname, int ttynamelen);
/*
* Releases the tty. Its ownership is returned to root, and permissions to
* 0666.
*/
void pty_release(const char *ttyname);
/*
* Makes the tty the processes controlling tty and sets it to sane modes.
* This may need to reopen the tty to get rid of possible eavesdroppers.
*/
void pty_make_controlling_tty(int *ttyfd, const char *ttyname);
/* Changes the window size associated with the pty. */
void
pty_change_window_size(int ptyfd, int row, int col,
int xpixel, int ypixel);
void pty_setowner(struct passwd *pw, const char *ttyname);
#endif /* PTY_H */

220
crypto/dist/ssh/radix.c vendored Normal file
View File

@ -0,0 +1,220 @@
/* $NetBSD: radix.c,v 1.1.1.1 2000/09/28 22:10:08 thorpej Exp $ */
/*
* Copyright (c) 1999 Dug Song. 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.
*/
/* from OpenBSD: radix.c,v 1.13 2000/09/07 20:27:52 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: radix.c,v 1.1.1.1 2000/09/28 22:10:08 thorpej Exp $");
#endif
#include "includes.h"
#include "uuencode.h"
#include "ssh.h"
#ifdef AFS
#include <krb.h>
typedef unsigned char my_u_char;
typedef unsigned int my_u_int32_t;
typedef unsigned short my_u_short;
/* Nasty macros from BIND-4.9.2 */
#define GETSHORT(s, cp) { \
register my_u_char *t_cp = (my_u_char*)(cp); \
(s) = (((my_u_short)t_cp[0]) << 8) \
| (((my_u_short)t_cp[1])) \
; \
(cp) += 2; \
}
#define GETLONG(l, cp) { \
register my_u_char *t_cp = (my_u_char*)(cp); \
(l) = (((my_u_int32_t)t_cp[0]) << 24) \
| (((my_u_int32_t)t_cp[1]) << 16) \
| (((my_u_int32_t)t_cp[2]) << 8) \
| (((my_u_int32_t)t_cp[3])) \
; \
(cp) += 4; \
}
#define PUTSHORT(s, cp) { \
register my_u_short t_s = (my_u_short)(s); \
register my_u_char *t_cp = (my_u_char*)(cp); \
*t_cp++ = t_s >> 8; \
*t_cp = t_s; \
(cp) += 2; \
}
#define PUTLONG(l, cp) { \
register my_u_int32_t t_l = (my_u_int32_t)(l); \
register my_u_char *t_cp = (my_u_char*)(cp); \
*t_cp++ = t_l >> 24; \
*t_cp++ = t_l >> 16; \
*t_cp++ = t_l >> 8; \
*t_cp = t_l; \
(cp) += 4; \
}
#define GETSTRING(s, p, p_l) { \
register char* p_targ = (p) + p_l; \
register char* s_c = (s); \
register char* p_c = (p); \
while (*p_c && (p_c < p_targ)) { \
*s_c++ = *p_c++; \
} \
if (p_c == p_targ) { \
return 1; \
} \
*s_c = *p_c++; \
(p_l) = (p_l) - (p_c - (p)); \
(p) = p_c; \
}
int
creds_to_radix(CREDENTIALS *creds, unsigned char *buf, size_t buflen)
{
char *p, *s;
int len;
char temp[2048];
p = temp;
*p++ = 1; /* version */
s = creds->service;
while (*s)
*p++ = *s++;
*p++ = *s;
s = creds->instance;
while (*s)
*p++ = *s++;
*p++ = *s;
s = creds->realm;
while (*s)
*p++ = *s++;
*p++ = *s;
s = creds->pname;
while (*s)
*p++ = *s++;
*p++ = *s;
s = creds->pinst;
while (*s)
*p++ = *s++;
*p++ = *s;
/* Null string to repeat the realm. */
*p++ = '\0';
PUTLONG(creds->issue_date, p);
{
unsigned int endTime;
endTime = (unsigned int) krb_life_to_time(creds->issue_date,
creds->lifetime);
PUTLONG(endTime, p);
}
memcpy(p, &creds->session, sizeof(creds->session));
p += sizeof(creds->session);
PUTSHORT(creds->kvno, p);
PUTLONG(creds->ticket_st.length, p);
memcpy(p, creds->ticket_st.dat, creds->ticket_st.length);
p += creds->ticket_st.length;
len = p - temp;
return (uuencode((unsigned char *)temp, len, (char *)buf, buflen));
}
int
radix_to_creds(const char *buf, CREDENTIALS *creds)
{
char *p;
int len, tl;
char version;
char temp[2048];
len = uudecode(buf, (unsigned char *)temp, sizeof(temp));
if (len < 0)
return 0;
p = temp;
/* check version and length! */
if (len < 1)
return 0;
version = *p;
p++;
len--;
GETSTRING(creds->service, p, len);
GETSTRING(creds->instance, p, len);
GETSTRING(creds->realm, p, len);
GETSTRING(creds->pname, p, len);
GETSTRING(creds->pinst, p, len);
/* Ignore possibly different realm. */
while (*p && len)
p++, len--;
if (len == 0)
return 0;
p++, len--;
/* Enough space for remaining fixed-length parts? */
if (len < (4 + 4 + sizeof(creds->session) + 2 + 4))
return 0;
GETLONG(creds->issue_date, p);
len -= 4;
{
unsigned int endTime;
GETLONG(endTime, p);
len -= 4;
creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
}
memcpy(&creds->session, p, sizeof(creds->session));
p += sizeof(creds->session);
len -= sizeof(creds->session);
GETSHORT(creds->kvno, p);
len -= 2;
GETLONG(creds->ticket_st.length, p);
len -= 4;
tl = creds->ticket_st.length;
if (tl < 0 || tl > len || tl > sizeof(creds->ticket_st.dat))
return 0;
memcpy(creds->ticket_st.dat, p, tl);
p += tl;
len -= tl;
return 1;
}
#endif /* AFS */

84
crypto/dist/ssh/random.c vendored Normal file
View File

@ -0,0 +1,84 @@
/* $NetBSD: random.c,v 1.1.1.1 2000/09/28 22:10:08 thorpej Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: random.c,v 1.1.1.1 2000/09/28 22:10:08 thorpej Exp $");
#endif
/*
* Functions for stirring in additional noise into the
* cryptographically strong PRNG.
*/
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <openssl/rand.h>
#include "includes.h"
#include "ssh.h"
#include "pathnames.h"
#define BUFSIZE 32
void
ssh_random_stir(void)
{
u_char buf[BUFSIZE];
ssize_t len;
int fd;
fd = open(_PATH_URANDOM, O_RDONLY, 0666);
if (fd != -1) {
len = read(fd, buf, sizeof(buf));
if (len != -1)
RAND_seed(buf, len);
(void) close(fd);
memset(buf, 0, sizeof(buf));
} else {
/*
* XXX We should stir in other environmental
* XXX noise, here.
*/
RAND_pseudo_bytes(buf, sizeof(buf) >> 1);
RAND_seed(buf, sizeof(buf) >> 1);
}
}

817
crypto/dist/ssh/readconf.c vendored Normal file
View File

@ -0,0 +1,817 @@
/* $NetBSD: readconf.c,v 1.1.1.1 2000/09/28 22:10:10 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for reading the configuration files.
*
* 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".
*/
/* from OpenBSD: readconf.c,v 1.47 2000/09/07 21:13:37 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: readconf.c,v 1.1.1.1 2000/09/28 22:10:10 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "cipher.h"
#include "pathnames.h"
#include "readconf.h"
#include "match.h"
#include "xmalloc.h"
#include "compat.h"
/* Format of the configuration file:
# Configuration data is parsed as follows:
# 1. command line options
# 2. user-specific file
# 3. system-wide file
# Any configuration value is only changed the first time it is set.
# Thus, host-specific definitions should be at the beginning of the
# configuration file, and defaults at the end.
# Host-specific declarations. These may override anything above. A single
# host may match multiple declarations; these are processed in the order
# that they are given in.
Host *.ngs.fi ngs.fi
FallBackToRsh no
Host fake.com
HostName another.host.name.real.org
User blaah
Port 34289
ForwardX11 no
ForwardAgent no
Host books.com
RemoteForward 9999 shadows.cs.hut.fi:9999
Cipher 3des
Host fascist.blob.com
Port 23123
User tylonen
RhostsAuthentication no
PasswordAuthentication no
Host puukko.hut.fi
User t35124p
ProxyCommand ssh-proxy %h %p
Host *.fr
UseRsh yes
Host *.su
Cipher none
PasswordAuthentication no
# Defaults for various options
Host *
ForwardAgent no
ForwardX11 yes
RhostsAuthentication yes
PasswordAuthentication yes
RSAAuthentication yes
RhostsRSAAuthentication yes
FallBackToRsh no
UseRsh no
StrictHostKeyChecking yes
KeepAlives no
IdentityFile ~/.ssh/identity
Port 22
EscapeChar ~
*/
/* Keyword tokens. */
typedef enum {
oBadOption,
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
oSkeyAuthentication, oXAuthLocation,
#ifdef KRB4
oKerberosAuthentication,
#endif /* KRB4 */
#ifdef AFS
oKerberosTgtPassing, oAFSTokenPassing,
#endif
oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2,
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication
} OpCodes;
/* Textual representations of the tokens. */
static struct {
const char *name;
OpCodes opcode;
} keywords[] = {
{ "forwardagent", oForwardAgent },
{ "forwardx11", oForwardX11 },
{ "xauthlocation", oXAuthLocation },
{ "gatewayports", oGatewayPorts },
{ "useprivilegedport", oUsePrivilegedPort },
{ "rhostsauthentication", oRhostsAuthentication },
{ "passwordauthentication", oPasswordAuthentication },
{ "rsaauthentication", oRSAAuthentication },
{ "dsaauthentication", oDSAAuthentication },
{ "skeyauthentication", oSkeyAuthentication },
#ifdef KRB4
{ "kerberosauthentication", oKerberosAuthentication },
#endif /* KRB4 */
#ifdef AFS
{ "kerberostgtpassing", oKerberosTgtPassing },
{ "afstokenpassing", oAFSTokenPassing },
#endif
{ "fallbacktorsh", oFallBackToRsh },
{ "usersh", oUseRsh },
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile2 },
{ "hostname", oHostName },
{ "proxycommand", oProxyCommand },
{ "port", oPort },
{ "cipher", oCipher },
{ "ciphers", oCiphers },
{ "protocol", oProtocol },
{ "remoteforward", oRemoteForward },
{ "localforward", oLocalForward },
{ "user", oUser },
{ "host", oHost },
{ "escapechar", oEscapeChar },
{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
{ "globalknownhostsfile", oGlobalKnownHostsFile },
{ "userknownhostsfile", oUserKnownHostsFile },
{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },
{ "userknownhostsfile2", oUserKnownHostsFile2 },
{ "connectionattempts", oConnectionAttempts },
{ "batchmode", oBatchMode },
{ "checkhostip", oCheckHostIP },
{ "stricthostkeychecking", oStrictHostKeyChecking },
{ "compression", oCompression },
{ "compressionlevel", oCompressionLevel },
{ "keepalive", oKeepAlives },
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
{ "tisauthentication", oTISAuthentication },
{ "loglevel", oLogLevel },
{ NULL, 0 }
};
/*
* Adds a local TCP/IP port forward to options. Never returns if there is an
* error.
*/
void
add_local_forward(Options *options, u_short port, const char *host,
u_short host_port)
{
Forward *fwd;
extern uid_t original_real_uid;
if (port < IPPORT_RESERVED && original_real_uid != 0)
fatal("Privileged ports can only be forwarded by root.\n");
if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
fwd = &options->local_forwards[options->num_local_forwards++];
fwd->port = port;
fwd->host = xstrdup(host);
fwd->host_port = host_port;
}
/*
* Adds a remote TCP/IP port forward to options. Never returns if there is
* an error.
*/
void
add_remote_forward(Options *options, u_short port, const char *host,
u_short host_port)
{
Forward *fwd;
if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
fatal("Too many remote forwards (max %d).",
SSH_MAX_FORWARDS_PER_DIRECTION);
fwd = &options->remote_forwards[options->num_remote_forwards++];
fwd->port = port;
fwd->host = xstrdup(host);
fwd->host_port = host_port;
}
/*
* Returns the number of the token pointed to by cp of length len. Never
* returns if the token is not known.
*/
static OpCodes
parse_token(const char *cp, const char *filename, int linenum)
{
unsigned int i;
for (i = 0; keywords[i].name; i++)
if (strcasecmp(cp, keywords[i].name) == 0)
return keywords[i].opcode;
fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
filename, linenum, cp);
return oBadOption;
}
/*
* Processes a single option line as used in the configuration files. This
* only sets those values that have not already been set.
*/
int
process_config_line(Options *options, const char *host,
char *line, const char *filename, int linenum,
int *activep)
{
char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg;
int opcode, *intptr, value;
u_short fwd_port, fwd_host_port;
s = line;
/* Get the keyword. (Each line is supposed to begin with a keyword). */
keyword = strdelim(&s);
/* Ignore leading whitespace. */
if (*keyword == '\0')
keyword = strdelim(&s);
if (!*keyword || *keyword == '\n' || *keyword == '#')
return 0;
opcode = parse_token(keyword, filename, linenum);
switch (opcode) {
case oBadOption:
/* don't panic, but count bad options */
return -1;
/* NOTREACHED */
case oForwardAgent:
intptr = &options->forward_agent;
parse_flag:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
value = 0; /* To avoid compiler warning... */
if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
value = 1;
else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
value = 0;
else
fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
if (*activep && *intptr == -1)
*intptr = value;
break;
case oForwardX11:
intptr = &options->forward_x11;
goto parse_flag;
case oGatewayPorts:
intptr = &options->gateway_ports;
goto parse_flag;
case oUsePrivilegedPort:
intptr = &options->use_privileged_port;
goto parse_flag;
case oRhostsAuthentication:
intptr = &options->rhosts_authentication;
goto parse_flag;
case oPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
case oDSAAuthentication:
intptr = &options->dsa_authentication;
goto parse_flag;
case oRSAAuthentication:
intptr = &options->rsa_authentication;
goto parse_flag;
case oRhostsRSAAuthentication:
intptr = &options->rhosts_rsa_authentication;
goto parse_flag;
case oTISAuthentication:
/* fallthrough, there is no difference on the client side */
case oSkeyAuthentication:
intptr = &options->skey_authentication;
goto parse_flag;
#ifdef KRB4
case oKerberosAuthentication:
intptr = &options->kerberos_authentication;
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing v4/v5/no argument.",
filename, linenum);
value = 0; /* To avoid compiler warning... */
if (strcmp(arg, "v4") == 0)
value = 4;
else if (strcmp(arg, "v5") == 0)
value = 5;
else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
value = 0;
else
fatal("%.200s line %d: Bad v4/v5/no argument.",
filename, linenum);
if (*activep && *intptr == -1)
*intptr = value;
break;
#endif /* KRB4 */
#ifdef AFS
case oKerberosTgtPassing:
intptr = &options->kerberos_tgt_passing;
goto parse_flag;
case oAFSTokenPassing:
intptr = &options->afs_token_passing;
goto parse_flag;
#endif
case oFallBackToRsh:
intptr = &options->fallback_to_rsh;
goto parse_flag;
case oUseRsh:
intptr = &options->use_rsh;
goto parse_flag;
case oBatchMode:
intptr = &options->batch_mode;
goto parse_flag;
case oCheckHostIP:
intptr = &options->check_host_ip;
goto parse_flag;
case oStrictHostKeyChecking:
intptr = &options->strict_host_key_checking;
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing yes/no argument.",
filename, linenum);
value = 0; /* To avoid compiler warning... */
if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
value = 1;
else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
value = 0;
else if (strcmp(arg, "ask") == 0)
value = 2;
else
fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
if (*activep && *intptr == -1)
*intptr = value;
break;
case oCompression:
intptr = &options->compression;
goto parse_flag;
case oKeepAlives:
intptr = &options->keepalives;
goto parse_flag;
case oNumberOfPasswordPrompts:
intptr = &options->number_of_password_prompts;
goto parse_int;
case oCompressionLevel:
intptr = &options->compression_level;
goto parse_int;
case oIdentityFile:
case oIdentityFile2:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (*activep) {
intptr = (opcode == oIdentityFile) ?
&options->num_identity_files :
&options->num_identity_files2;
if (*intptr >= SSH_MAX_IDENTITY_FILES)
fatal("%.200s line %d: Too many identity files specified (max %d).",
filename, linenum, SSH_MAX_IDENTITY_FILES);
charptr = (opcode == oIdentityFile) ?
&options->identity_files[*intptr] :
&options->identity_files2[*intptr];
*charptr = xstrdup(arg);
*intptr = *intptr + 1;
}
break;
case oXAuthLocation:
charptr=&options->xauth_location;
goto parse_string;
case oUser:
charptr = &options->user;
parse_string:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case oGlobalKnownHostsFile:
charptr = &options->system_hostfile;
goto parse_string;
case oUserKnownHostsFile:
charptr = &options->user_hostfile;
goto parse_string;
case oGlobalKnownHostsFile2:
charptr = &options->system_hostfile2;
goto parse_string;
case oUserKnownHostsFile2:
charptr = &options->user_hostfile2;
goto parse_string;
case oHostName:
charptr = &options->hostname;
goto parse_string;
case oProxyCommand:
charptr = &options->proxy_command;
string = xstrdup("");
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
string = xrealloc(string, strlen(string) + strlen(arg) + 2);
strcat(string, " ");
strcat(string, arg);
}
if (*activep && *charptr == NULL)
*charptr = string;
else
xfree(string);
return 0;
case oPort:
intptr = &options->port;
parse_int:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (arg[0] < '0' || arg[0] > '9')
fatal("%.200s line %d: Bad number.", filename, linenum);
/* Octal, decimal, or hex format? */
value = strtol(arg, &endofnumber, 0);
if (arg == endofnumber)
fatal("%.200s line %d: Bad number.", filename, linenum);
if (*activep && *intptr == -1)
*intptr = value;
break;
case oConnectionAttempts:
intptr = &options->connection_attempts;
goto parse_int;
case oCipher:
intptr = &options->cipher;
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
value = cipher_number(arg);
if (value == -1)
fatal("%.200s line %d: Bad cipher '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && *intptr == -1)
*intptr = value;
break;
case oCiphers:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (!ciphers_valid(arg))
fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->ciphers == NULL)
options->ciphers = xstrdup(arg);
break;
case oProtocol:
intptr = &options->protocol;
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
value = proto_spec(arg);
if (value == SSH_PROTO_UNKNOWN)
fatal("%.200s line %d: Bad protocol spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && *intptr == SSH_PROTO_UNKNOWN)
*intptr = value;
break;
case oLogLevel:
intptr = (int *) &options->log_level;
arg = strdelim(&s);
value = log_level_number(arg);
if (value == (LogLevel) - 1)
fatal("%.200s line %d: unsupported log level '%s'\n",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && (LogLevel) * intptr == -1)
*intptr = (LogLevel) value;
break;
case oRemoteForward:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (arg[0] < '0' || arg[0] > '9')
fatal("%.200s line %d: Badly formatted port number.",
filename, linenum);
fwd_port = atoi(arg);
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing second argument.",
filename, linenum);
if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
fatal("%.200s line %d: Badly formatted host:port.",
filename, linenum);
if (*activep)
add_remote_forward(options, fwd_port, buf, fwd_host_port);
break;
case oLocalForward:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (arg[0] < '0' || arg[0] > '9')
fatal("%.200s line %d: Badly formatted port number.",
filename, linenum);
fwd_port = atoi(arg);
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing second argument.",
filename, linenum);
if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
fatal("%.200s line %d: Badly formatted host:port.",
filename, linenum);
if (*activep)
add_local_forward(options, fwd_port, buf, fwd_host_port);
break;
case oHost:
*activep = 0;
while ((arg = strdelim(&s)) != NULL && *arg != '\0')
if (match_pattern(host, arg)) {
debug("Applying options for %.100s", arg);
*activep = 1;
break;
}
/* Avoid garbage check below, as strdelim is done. */
return 0;
case oEscapeChar:
intptr = &options->escape_char;
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (arg[0] == '^' && arg[2] == 0 &&
(unsigned char) arg[1] >= 64 && (unsigned char) arg[1] < 128)
value = (unsigned char) arg[1] & 31;
else if (strlen(arg) == 1)
value = (unsigned char) arg[0];
else if (strcmp(arg, "none") == 0)
value = -2;
else {
fatal("%.200s line %d: Bad escape character.",
filename, linenum);
/* NOTREACHED */
value = 0; /* Avoid compiler warning. */
}
if (*activep && *intptr == -1)
*intptr = value;
break;
default:
fatal("process_config_line: Unimplemented opcode %d", opcode);
}
/* Check that there is no garbage at end of line. */
if ((arg = strdelim(&s)) != NULL && *arg != '\0')
{
fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
filename, linenum, arg);
}
return 0;
}
/*
* Reads the config file and modifies the options accordingly. Options
* should already be initialized before this call. This never returns if
* there is an error. If the file does not exist, this returns immediately.
*/
void
read_config_file(const char *filename, const char *host, Options *options)
{
FILE *f;
char line[1024];
int active, linenum;
int bad_options = 0;
/* Open the file. */
f = fopen(filename, "r");
if (!f)
return;
debug("Reading configuration data %.200s", filename);
/*
* Mark that we are now processing the options. This flag is turned
* on/off by Host specifications.
*/
active = 1;
linenum = 0;
while (fgets(line, sizeof(line), f)) {
/* Update line number counter. */
linenum++;
if (process_config_line(options, host, line, filename, linenum, &active) != 0)
bad_options++;
}
fclose(f);
if (bad_options > 0)
fatal("%s: terminating, %d bad configuration options\n",
filename, bad_options);
}
/*
* Initializes options to special values that indicate that they have not yet
* been set. Read_config_file will only set options with this value. Options
* are processed in the following order: command line, user config file,
* system config file. Last, fill_default_options is called.
*/
void
initialize_options(Options * options)
{
memset(options, 'X', sizeof(*options));
options->forward_agent = -1;
options->forward_x11 = -1;
options->xauth_location = NULL;
options->gateway_ports = -1;
options->use_privileged_port = -1;
options->rhosts_authentication = -1;
options->rsa_authentication = -1;
options->dsa_authentication = -1;
options->skey_authentication = -1;
#ifdef KRB4
options->kerberos_authentication = -1;
#endif
#ifdef AFS
options->kerberos_tgt_passing = -1;
options->afs_token_passing = -1;
#endif
options->password_authentication = -1;
options->rhosts_rsa_authentication = -1;
options->fallback_to_rsh = -1;
options->use_rsh = -1;
options->batch_mode = -1;
options->check_host_ip = -1;
options->strict_host_key_checking = -1;
options->compression = -1;
options->keepalives = -1;
options->compression_level = -1;
options->port = -1;
options->connection_attempts = -1;
options->number_of_password_prompts = -1;
options->cipher = -1;
options->ciphers = NULL;
options->protocol = SSH_PROTO_UNKNOWN;
options->num_identity_files = 0;
options->num_identity_files2 = 0;
options->hostname = NULL;
options->proxy_command = NULL;
options->user = NULL;
options->escape_char = -1;
options->system_hostfile = NULL;
options->user_hostfile = NULL;
options->system_hostfile2 = NULL;
options->user_hostfile2 = NULL;
options->num_local_forwards = 0;
options->num_remote_forwards = 0;
options->log_level = (LogLevel) - 1;
}
/*
* Called after processing other sources of option data, this fills those
* options for which no value has been specified with their default values.
*/
void
fill_default_options(Options * options)
{
if (options->forward_agent == -1)
options->forward_agent = 0;
if (options->forward_x11 == -1)
options->forward_x11 = 0;
#ifdef _PATH_XAUTH
if (options->xauth_location == NULL)
options->xauth_location = _PATH_XAUTH;
#endif /* _PATH_XAUTH */
if (options->gateway_ports == -1)
options->gateway_ports = 0;
if (options->use_privileged_port == -1)
options->use_privileged_port = 1;
if (options->rhosts_authentication == -1)
options->rhosts_authentication = 1;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
if (options->dsa_authentication == -1)
options->dsa_authentication = 1;
if (options->skey_authentication == -1)
options->skey_authentication = 1;
#ifdef KRB4
if (options->kerberos_authentication == -1)
options->kerberos_authentication = 4;
#endif /* KRB4 */
#ifdef AFS
if (options->kerberos_tgt_passing == -1)
options->kerberos_tgt_passing = 1;
if (options->afs_token_passing == -1)
options->afs_token_passing = 1;
#endif /* AFS */
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->rhosts_rsa_authentication == -1)
options->rhosts_rsa_authentication = 1;
if (options->fallback_to_rsh == -1)
options->fallback_to_rsh = 0;
if (options->use_rsh == -1)
options->use_rsh = 0;
if (options->batch_mode == -1)
options->batch_mode = 0;
if (options->check_host_ip == -1)
options->check_host_ip = 0;
if (options->strict_host_key_checking == -1)
options->strict_host_key_checking = 2; /* 2 is default */
if (options->compression == -1)
options->compression = 0;
if (options->keepalives == -1)
options->keepalives = 1;
if (options->compression_level == -1)
options->compression_level = 6;
if (options->port == -1)
options->port = 0; /* Filled in ssh_connect. */
if (options->connection_attempts == -1)
options->connection_attempts = 4;
if (options->number_of_password_prompts == -1)
options->number_of_password_prompts = 3;
/* Selected in ssh_login(). */
if (options->cipher == -1)
options->cipher = SSH_CIPHER_NOT_SET;
/* options->ciphers, default set in myproposals.h */
if (options->protocol == SSH_PROTO_UNKNOWN)
options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
if (options->num_identity_files == 0) {
options->identity_files[0] =
xmalloc(2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1);
sprintf(options->identity_files[0], "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
options->num_identity_files = 1;
}
if (options->num_identity_files2 == 0) {
options->identity_files2[0] =
xmalloc(2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1);
sprintf(options->identity_files2[0], "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
options->num_identity_files2 = 1;
}
if (options->escape_char == -1)
options->escape_char = '~';
if (options->system_hostfile == NULL)
options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
if (options->user_hostfile == NULL)
options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
if (options->system_hostfile2 == NULL)
options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
if (options->user_hostfile2 == NULL)
options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
if (options->log_level == (LogLevel) - 1)
options->log_level = SYSLOG_LEVEL_INFO;
/* options->proxy_command should not be set by default */
/* options->user will be set in the main program if appropriate */
/* options->hostname will be set in the main program if appropriate */
}

145
crypto/dist/ssh/readconf.h vendored Normal file
View File

@ -0,0 +1,145 @@
/* $NetBSD: readconf.h,v 1.1.1.1 2000/09/28 22:10:10 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for reading the configuration file.
*
* 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".
*/
/* from OpenBSD: readconf.h,v 1.21 2000/09/07 20:27:53 deraadt Exp */
#ifndef READCONF_H
#define READCONF_H
/* Data structure for representing a forwarding request. */
typedef struct {
u_short port; /* Port to forward. */
char *host; /* Host to connect. */
u_short host_port; /* Port to connect on host. */
} Forward;
/* Data structure for representing option data. */
typedef struct {
int forward_agent; /* Forward authentication agent. */
int forward_x11; /* Forward X11 display. */
char *xauth_location; /* Location for xauth program */
int gateway_ports; /* Allow remote connects to forwarded ports. */
int use_privileged_port; /* Don't use privileged port if false. */
int rhosts_authentication; /* Try rhosts authentication. */
int rhosts_rsa_authentication; /* Try rhosts with RSA
* authentication. */
int rsa_authentication; /* Try RSA authentication. */
int dsa_authentication; /* Try DSA authentication. */
int skey_authentication; /* Try S/Key or TIS authentication. */
#ifdef KRB4
int kerberos_authentication; /* Try Kerberos
* authentication. */
#endif
#ifdef AFS
int kerberos_tgt_passing; /* Try Kerberos tgt passing. */
int afs_token_passing; /* Try AFS token passing. */
#endif
int password_authentication; /* Try password
* authentication. */
int fallback_to_rsh;/* Use rsh if cannot connect with ssh. */
int use_rsh; /* Always use rsh (don\'t try ssh). */
int batch_mode; /* Batch mode: do not ask for passwords. */
int check_host_ip; /* Also keep track of keys for IP address */
int strict_host_key_checking; /* Strict host key checking. */
int compression; /* Compress packets in both directions. */
int compression_level; /* Compression level 1 (fast) to 9
* (best). */
int keepalives; /* Set SO_KEEPALIVE. */
LogLevel log_level; /* Level for logging. */
int port; /* Port to connect. */
int connection_attempts; /* Max attempts (seconds) before
* giving up */
int number_of_password_prompts; /* Max number of password
* prompts. */
int cipher; /* Cipher to use. */
char *ciphers; /* SSH2 ciphers in order of preference. */
int protocol; /* Protocol in order of preference. */
char *hostname; /* Real host to connect. */
char *proxy_command; /* Proxy command for connecting the host. */
char *user; /* User to log in as. */
int escape_char; /* Escape character; -2 = none */
char *system_hostfile;/* Path for /etc/ssh_known_hosts. */
char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */
char *system_hostfile2;
char *user_hostfile2;
int num_identity_files; /* Number of files for RSA identities. */
int num_identity_files2; /* DSA identities. */
char *identity_files[SSH_MAX_IDENTITY_FILES];
char *identity_files2[SSH_MAX_IDENTITY_FILES];
/* Local TCP/IP forward requests. */
int num_local_forwards;
Forward local_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
/* Remote TCP/IP forward requests. */
int num_remote_forwards;
Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
} Options;
/*
* Initializes options to special values that indicate that they have not yet
* been set. Read_config_file will only set options with this value. Options
* are processed in the following order: command line, user config file,
* system config file. Last, fill_default_options is called.
*/
void initialize_options(Options * options);
/*
* Called after processing other sources of option data, this fills those
* options for which no value has been specified with their default values.
*/
void fill_default_options(Options * options);
/*
* Processes a single option line as used in the configuration files. This
* only sets those values that have not already been set. Returns 0 for legal
* options
*/
int
process_config_line(Options * options, const char *host,
char *line, const char *filename, int linenum,
int *activep);
/*
* Reads the config file and modifies the options accordingly. Options
* should already be initialized before this call. This never returns if
* there is an error. If the file does not exist, this returns immediately.
*/
void
read_config_file(const char *filename, const char *host,
Options * options);
/*
* Adds a local TCP/IP port forward to options. Never returns if there is an
* error.
*/
void
add_local_forward(Options * options, u_short port, const char *host,
u_short host_port);
/*
* Adds a remote TCP/IP port forward to options. Never returns if there is
* an error.
*/
void
add_remote_forward(Options * options, u_short port, const char *host,
u_short host_port);
#endif /* READCONF_H */

127
crypto/dist/ssh/readpass.c vendored Normal file
View File

@ -0,0 +1,127 @@
/* $NetBSD: readpass.c,v 1.1.1.1 2000/09/28 22:10:10 thorpej Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* from OpenBSD: readpass.c,v 1.11 2000/06/20 01:39:44 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: readpass.c,v 1.1.1.1 2000/09/28 22:10:10 thorpej Exp $");
#endif
#include "includes.h"
#include "xmalloc.h"
#include "ssh.h"
volatile int intr;
static void
intcatch(int signo)
{
intr = 1;
}
/*
* Reads a passphrase from /dev/tty with echo turned off. Returns the
* passphrase (allocated with xmalloc), being very careful to ensure that
* no other userland buffer is storing the password.
*/
char *
read_passphrase(const char *prompt, int from_stdin)
{
char buf[1024], *p, ch;
struct termios tio, saved_tio;
sigset_t oset, nset;
struct sigaction sa, osa;
int input, output, echo = 0;
if (from_stdin) {
input = STDIN_FILENO;
output = STDERR_FILENO;
} else
input = output = open(_PATH_TTY, O_RDWR);
if (input == -1)
fatal("You have no controlling tty. Cannot read passphrase.\n");
/* block signals, get terminal modes and turn off echo */
sigemptyset(&nset);
sigaddset(&nset, SIGTSTP);
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
memset(&sa, 0, sizeof(sa));
sa.sa_handler = intcatch;
(void) sigaction(SIGINT, &sa, &osa);
intr = 0;
if (tcgetattr(input, &saved_tio) == 0 && (saved_tio.c_lflag & ECHO)) {
echo = 1;
tio = saved_tio;
tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
(void) tcsetattr(input, TCSANOW, &tio);
}
fflush(stdout);
(void)write(output, prompt, strlen(prompt));
for (p = buf; read(input, &ch, 1) == 1 && ch != '\n';) {
if (intr)
break;
if (p < buf + sizeof(buf) - 1)
*p++ = ch;
}
*p = '\0';
if (!intr)
(void)write(output, "\n", 1);
/* restore terminal modes and allow signals */
if (echo)
tcsetattr(input, TCSANOW, &saved_tio);
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
(void) sigaction(SIGINT, &osa, NULL);
if (intr) {
kill(getpid(), SIGINT);
sigemptyset(&nset);
/* XXX tty has not neccessarily drained by now? */
sigsuspend(&nset);
}
if (!from_stdin)
(void)close(input);
p = xstrdup(buf);
memset(buf, 0, sizeof(buf));
return (p);
}

202
crypto/dist/ssh/rsa.c vendored Normal file
View File

@ -0,0 +1,202 @@
/* $NetBSD: rsa.c,v 1.1.1.1 2000/09/28 22:10:11 thorpej 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) 1999 Niels Provos. 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.
*
*
* Description of the RSA algorithm can be found e.g. from the following
* sources:
*
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
*
* Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to
* Computer Security. Prentice-Hall, 1989.
*
* Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill,
* 1994.
*
* R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications
* System and Method. US Patent 4,405,829, 1983.
*
* Hans Riesel: Prime Numbers and Computer Methods for Factorization.
* Birkhauser, 1994.
*
* The RSA Frequently Asked Questions document by RSA Data Security,
* Inc., 1995.
*
* RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as
* included below:
*
* [gone - had to be deleted - what a pity]
*/
/* from OpenBSD: rsa.c,v 1.16 2000/09/07 20:27:53 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: rsa.c,v 1.1.1.1 2000/09/28 22:10:11 thorpej Exp $");
#endif
#include "includes.h"
#include "rsa.h"
#include "ssh.h"
#include "xmalloc.h"
int rsa_verbose = 1;
int
rsa_alive()
{
RSA *key;
key = RSA_generate_key(32, 3, NULL, NULL);
if (key == NULL)
return (0);
RSA_free(key);
return (1);
}
/*
* Generates RSA public and private keys. This initializes the data
* structures; they should be freed with rsa_clear_private_key and
* rsa_clear_public_key.
*/
void
rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits)
{
RSA *key;
if (rsa_verbose) {
printf("Generating RSA keys: ");
fflush(stdout);
}
key = RSA_generate_key(bits, 35, NULL, NULL);
if (key == NULL)
fatal("rsa_generate_key: key generation failed.");
/* Copy public key parameters */
pub->n = BN_new();
BN_copy(pub->n, key->n);
pub->e = BN_new();
BN_copy(pub->e, key->e);
/* Copy private key parameters */
prv->n = BN_new();
BN_copy(prv->n, key->n);
prv->e = BN_new();
BN_copy(prv->e, key->e);
prv->d = BN_new();
BN_copy(prv->d, key->d);
prv->p = BN_new();
BN_copy(prv->p, key->p);
prv->q = BN_new();
BN_copy(prv->q, key->q);
prv->dmp1 = BN_new();
BN_copy(prv->dmp1, key->dmp1);
prv->dmq1 = BN_new();
BN_copy(prv->dmq1, key->dmq1);
prv->iqmp = BN_new();
BN_copy(prv->iqmp, key->iqmp);
RSA_free(key);
if (rsa_verbose)
printf("Key generation complete.\n");
}
void
rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
{
unsigned char *inbuf, *outbuf;
int len, ilen, olen;
if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
fatal("rsa_public_encrypt() exponent too small or not odd");
olen = BN_num_bytes(key->n);
outbuf = xmalloc(olen);
ilen = BN_num_bytes(in);
inbuf = xmalloc(ilen);
BN_bn2bin(in, inbuf);
if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key,
RSA_PKCS1_PADDING)) <= 0)
fatal("rsa_public_encrypt() failed");
BN_bin2bn(outbuf, len, out);
memset(outbuf, 0, olen);
memset(inbuf, 0, ilen);
xfree(outbuf);
xfree(inbuf);
}
void
rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
{
unsigned char *inbuf, *outbuf;
int len, ilen, olen;
olen = BN_num_bytes(key->n);
outbuf = xmalloc(olen);
ilen = BN_num_bytes(in);
inbuf = xmalloc(ilen);
BN_bn2bin(in, inbuf);
if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
RSA_PKCS1_PADDING)) <= 0)
fatal("rsa_private_decrypt() failed");
BN_bin2bn(outbuf, len, out);
memset(outbuf, 0, olen);
memset(inbuf, 0, ilen);
xfree(outbuf);
xfree(inbuf);
}
/* Set whether to output verbose messages during key generation. */
void
rsa_set_verbose(int verbose)
{
rsa_verbose = verbose;
}

38
crypto/dist/ssh/rsa.h vendored Normal file
View File

@ -0,0 +1,38 @@
/* $NetBSD: rsa.h,v 1.1.1.1 2000/09/28 22:10:11 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* RSA key generation, encryption and decryption.
*
* 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".
*/
/* from OpenBSD: rsa.h,v 1.8 2000/09/07 20:27:53 deraadt Exp */
#ifndef RSA_H
#define RSA_H
#include <openssl/bn.h>
#include <openssl/rsa.h>
/* Calls SSL RSA_generate_key, only copies to prv and pub */
void rsa_generate_key(RSA * prv, RSA * pub, unsigned int bits);
/*
* Indicates whether the rsa module is permitted to show messages on the
* terminal.
*/
void rsa_set_verbose __P((int verbose));
int rsa_alive __P((void));
void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
void rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
#endif /* RSA_H */

132
crypto/dist/ssh/scp.1 vendored Normal file
View File

@ -0,0 +1,132 @@
.\" -*- nroff -*-
.\"
.\" scp.1
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\"
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
.\" All rights reserved
.\"
.\" Created: Sun May 7 00:14:37 1995 ylo
.\"
.\" $NetBSD: scp.1,v 1.1.1.1 2000/09/28 22:10:11 thorpej Exp $
.\"
.Dd September 25, 1999
.Dt SCP 1
.Os
.Sh NAME
.Nm scp
.Nd secure copy (remote file copy program)
.Sh SYNOPSIS
.Nm scp
.Op Fl pqrvC46
.Op Fl S Ar program
.Op Fl P Ar port
.Op Fl c Ar cipher
.Op Fl i Ar identity_file
.Sm off
.Oo
.Op Ar user@
.Ar host1 No :
.Oc Ns Ar file1
.Sm on
.Op Ar ...
.Sm off
.Oo
.Op Ar user@
.Ar host2 No :
.Oc Ar file2
.Sm on
.Sh DESCRIPTION
.Nm
copies files between hosts on a network.
It uses
.Xr ssh 1
for data transfer, and uses the same authentication and provides the
same security as
.Xr ssh 1 .
Unlike
.Xr rcp 1 ,
.Nm
will ask for passwords or passphrases if they are needed for
authentication.
.Pp
Any file name may contain a host and user specification to indicate
that the file is to be copied to/from that host.
Copies between two remote hosts are permitted.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl c Ar cipher
Selects the cipher to use for encrypting the data transfer.
This option is directly passed to
.Xr ssh 1 .
.It Fl i Ar identity_file
Selects the file from which the identity (private key) for RSA
authentication is read.
This option is directly passed to
.Xr ssh 1 .
.It Fl p
Preserves modification times, access times, and modes from the
original file.
.It Fl r
Recursively copy entire directories.
.It Fl v
Verbose mode.
Causes
.Nm
and
.Xr ssh 1
to print debugging messages about their progress.
This is helpful in
debugging connection, authentication, and configuration problems.
.It Fl B
Selects batch mode (prevents asking for passwords or passphrases).
.It Fl q
Disables the progress meter.
.It Fl C
Compression enable.
Passes the
.Fl C
flag to
.Xr ssh 1
to enable compression.
.It Fl P Ar port
Specifies the port to connect to on the remote host.
Note that this option is written with a capital
.Sq P ,
because
.Fl p
is already reserved for preserving the times and modes of the file in
.Xr rcp 1 .
.It Fl S Ar program
Name of
.Ar program
to use for the encrypted connection. The program must understand
.Xr ssh 1
options.
.It Fl 4
Forces
.Nm
to use IPv4 addresses only.
.It Fl 6
Forces
.Nm
to use IPv6 addresses only.
.El
.Sh AUTHORS
Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi>, Theo de Raadt,
Aaron Campbell
.Sh HISTORY
.Nm
is based on the
.Xr rcp 1
program in BSD source code from the Regents of the University of
California.
.Sh SEE ALSO
.Xr rcp 1 ,
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
.Xr sshd 8

1259
crypto/dist/ssh/scp.c vendored Normal file

File diff suppressed because it is too large Load Diff

697
crypto/dist/ssh/servconf.c vendored Normal file
View File

@ -0,0 +1,697 @@
/* $NetBSD: servconf.c,v 1.1.1.1 2000/09/28 22:10:15 thorpej Exp $ */
/*
* 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".
*/
/* from OpenBSD: servconf.c,v 1.51 2000/09/07 20:27:53 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: servconf.c,v 1.1.1.1 2000/09/28 22:10:15 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "pathnames.h"
#include "servconf.h"
#include "xmalloc.h"
#include "compat.h"
/* add listen address */
void add_listen_addr(ServerOptions *options, char *addr);
/* Initializes the server options to their default values. */
void
initialize_server_options(ServerOptions *options)
{
memset(options, 0, sizeof(*options));
options->num_ports = 0;
options->ports_from_cmdline = 0;
options->listen_addrs = NULL;
options->host_key_file = NULL;
options->host_dsa_key_file = NULL;
options->pid_file = NULL;
options->server_key_bits = -1;
options->login_grace_time = -1;
options->key_regeneration_time = -1;
options->permit_root_login = -1;
options->ignore_rhosts = -1;
options->ignore_user_known_hosts = -1;
options->print_motd = -1;
options->check_mail = -1;
options->x11_forwarding = -1;
options->x11_display_offset = -1;
options->xauth_location = NULL;
options->strict_modes = -1;
options->keepalives = -1;
options->log_facility = (SyslogFacility) - 1;
options->log_level = (LogLevel) - 1;
options->rhosts_authentication = -1;
options->rhosts_rsa_authentication = -1;
options->rsa_authentication = -1;
options->dsa_authentication = -1;
#ifdef KRB4
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
#endif
#ifdef AFS
options->kerberos_tgt_passing = -1;
options->afs_token_passing = -1;
#endif
options->password_authentication = -1;
#ifdef SKEY
options->skey_authentication = -1;
#endif
options->permit_empty_passwd = -1;
options->use_login = -1;
options->num_allow_users = 0;
options->num_deny_users = 0;
options->num_allow_groups = 0;
options->num_deny_groups = 0;
options->ciphers = NULL;
options->protocol = SSH_PROTO_UNKNOWN;
options->gateway_ports = -1;
options->num_subsystems = 0;
options->max_startups_begin = -1;
options->max_startups_rate = -1;
options->max_startups = -1;
}
void
fill_default_server_options(ServerOptions *options)
{
if (options->num_ports == 0)
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
if (options->listen_addrs == NULL)
add_listen_addr(options, NULL);
if (options->host_key_file == NULL)
options->host_key_file = _PATH_HOST_KEY_FILE;
if (options->host_dsa_key_file == NULL)
options->host_dsa_key_file = _PATH_HOST_DSA_KEY_FILE;
if (options->pid_file == NULL)
options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
if (options->server_key_bits == -1)
options->server_key_bits = 768;
if (options->login_grace_time == -1)
options->login_grace_time = 600;
if (options->key_regeneration_time == -1)
options->key_regeneration_time = 3600;
if (options->permit_root_login == -1)
options->permit_root_login = 1; /* yes */
if (options->ignore_rhosts == -1)
options->ignore_rhosts = 1;
if (options->ignore_user_known_hosts == -1)
options->ignore_user_known_hosts = 0;
if (options->check_mail == -1)
options->check_mail = 0;
if (options->print_motd == -1)
options->print_motd = 1;
if (options->x11_forwarding == -1)
options->x11_forwarding = 0;
if (options->x11_display_offset == -1)
options->x11_display_offset = 10;
#ifdef _PATH_XAUTH
if (options->xauth_location == NULL)
options->xauth_location = _PATH_XAUTH;
#endif /* _PATH_XAUTH */
if (options->strict_modes == -1)
options->strict_modes = 1;
if (options->keepalives == -1)
options->keepalives = 1;
if (options->log_facility == (SyslogFacility) (-1))
options->log_facility = SYSLOG_FACILITY_AUTH;
if (options->log_level == (LogLevel) (-1))
options->log_level = SYSLOG_LEVEL_INFO;
if (options->rhosts_authentication == -1)
options->rhosts_authentication = 0;
if (options->rhosts_rsa_authentication == -1)
options->rhosts_rsa_authentication = 0;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
if (options->dsa_authentication == -1)
options->dsa_authentication = 1;
#ifdef KRB4
if (options->kerberos_authentication == -1)
options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
if (options->kerberos_or_local_passwd == -1)
options->kerberos_or_local_passwd = 1;
if (options->kerberos_ticket_cleanup == -1)
options->kerberos_ticket_cleanup = 1;
#endif /* KRB4 */
#ifdef AFS
if (options->kerberos_tgt_passing == -1)
options->kerberos_tgt_passing = 0;
if (options->afs_token_passing == -1)
options->afs_token_passing = k_hasafs();
#endif /* AFS */
if (options->password_authentication == -1)
options->password_authentication = 1;
#ifdef SKEY
if (options->skey_authentication == -1)
options->skey_authentication = 1;
#endif
if (options->permit_empty_passwd == -1)
options->permit_empty_passwd = 0;
if (options->use_login == -1)
options->use_login = 0;
if (options->protocol == SSH_PROTO_UNKNOWN)
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
if (options->gateway_ports == -1)
options->gateway_ports = 0;
if (options->max_startups == -1)
options->max_startups = 10;
if (options->max_startups_rate == -1)
options->max_startups_rate = 100; /* 100% */
if (options->max_startups_begin == -1)
options->max_startups_begin = options->max_startups;
}
/* Keyword tokens. */
typedef enum {
sBadOption, /* == unknown option */
sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
sPermitRootLogin, sLogFacility, sLogLevel,
sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
#ifdef KRB4
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
#endif
#ifdef AFS
sKerberosTgtPassing, sAFSTokenPassing,
#endif
#ifdef SKEY
sSkeyAuthentication,
#endif
sPasswordAuthentication, sListenAddress,
sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
sGatewayPorts, sDSAAuthentication, sXAuthLocation, sSubsystem, sMaxStartups
} ServerOpCodes;
/* Textual representation of the tokens. */
static struct {
const char *name;
ServerOpCodes opcode;
} keywords[] = {
{ "port", sPort },
{ "hostkey", sHostKeyFile },
{ "hostdsakey", sHostDSAKeyFile },
{ "pidfile", sPidFile },
{ "serverkeybits", sServerKeyBits },
{ "logingracetime", sLoginGraceTime },
{ "keyregenerationinterval", sKeyRegenerationTime },
{ "permitrootlogin", sPermitRootLogin },
{ "syslogfacility", sLogFacility },
{ "loglevel", sLogLevel },
{ "rhostsauthentication", sRhostsAuthentication },
{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
{ "rsaauthentication", sRSAAuthentication },
{ "dsaauthentication", sDSAAuthentication },
#ifdef KRB4
{ "kerberosauthentication", sKerberosAuthentication },
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
{ "kerberosticketcleanup", sKerberosTicketCleanup },
#endif
#ifdef AFS
{ "kerberostgtpassing", sKerberosTgtPassing },
{ "afstokenpassing", sAFSTokenPassing },
#endif
{ "passwordauthentication", sPasswordAuthentication },
#ifdef SKEY
{ "skeyauthentication", sSkeyAuthentication },
#endif
{ "checkmail", sCheckMail },
{ "listenaddress", sListenAddress },
{ "printmotd", sPrintMotd },
{ "ignorerhosts", sIgnoreRhosts },
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
{ "x11forwarding", sX11Forwarding },
{ "x11displayoffset", sX11DisplayOffset },
{ "xauthlocation", sXAuthLocation },
{ "strictmodes", sStrictModes },
{ "permitemptypasswords", sEmptyPasswd },
{ "uselogin", sUseLogin },
{ "randomseed", sRandomSeedFile },
{ "keepalive", sKeepAlives },
{ "allowusers", sAllowUsers },
{ "denyusers", sDenyUsers },
{ "allowgroups", sAllowGroups },
{ "denygroups", sDenyGroups },
{ "ciphers", sCiphers },
{ "protocol", sProtocol },
{ "gatewayports", sGatewayPorts },
{ "subsystem", sSubsystem },
{ "maxstartups", sMaxStartups },
{ NULL, 0 }
};
/*
* Returns the number of the token pointed to by cp of length len. Never
* returns if the token is not known.
*/
static ServerOpCodes
parse_token(const char *cp, const char *filename,
int linenum)
{
unsigned int i;
for (i = 0; keywords[i].name; i++)
if (strcasecmp(cp, keywords[i].name) == 0)
return keywords[i].opcode;
fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
filename, linenum, cp);
return sBadOption;
}
/*
* add listen address
*/
void
add_listen_addr(ServerOptions *options, char *addr)
{
extern int IPv4or6;
struct addrinfo hints, *ai, *aitop;
char strport[NI_MAXSERV];
int gaierr;
int i;
if (options->num_ports == 0)
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
for (i = 0; i < options->num_ports; i++) {
memset(&hints, 0, sizeof(hints));
hints.ai_family = IPv4or6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
snprintf(strport, sizeof strport, "%d", options->ports[i]);
if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
fatal("bad addr or host: %s (%s)\n",
addr ? addr : "<NULL>",
gai_strerror(gaierr));
for (ai = aitop; ai->ai_next; ai = ai->ai_next)
;
ai->ai_next = options->listen_addrs;
options->listen_addrs = aitop;
}
}
/* Reads the server configuration file. */
void
read_server_config(ServerOptions *options, const char *filename)
{
FILE *f;
char line[1024];
char *cp, **charptr, *arg;
int linenum, *intptr, value;
int bad_options = 0;
ServerOpCodes opcode;
int i;
f = fopen(filename, "r");
if (!f) {
perror(filename);
exit(1);
}
linenum = 0;
while (fgets(line, sizeof(line), f)) {
linenum++;
cp = line;
arg = strdelim(&cp);
/* Ignore leading whitespace */
if (*arg == '\0')
arg = strdelim(&cp);
if (!*arg || *arg == '#')
continue;
opcode = parse_token(arg, filename, linenum);
switch (opcode) {
case sBadOption:
bad_options++;
continue;
case sPort:
/* ignore ports from configfile if cmdline specifies ports */
if (options->ports_from_cmdline)
continue;
if (options->listen_addrs != NULL)
fatal("%s line %d: ports must be specified before "
"ListenAdress.\n", filename, linenum);
if (options->num_ports >= MAX_PORTS)
fatal("%s line %d: too many ports.\n",
filename, linenum);
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing port number.\n",
filename, linenum);
options->ports[options->num_ports++] = atoi(arg);
break;
case sServerKeyBits:
intptr = &options->server_key_bits;
parse_int:
arg = strdelim(&cp);
if (!arg || *arg == '\0') {
fprintf(stderr, "%s line %d: missing integer value.\n",
filename, linenum);
exit(1);
}
value = atoi(arg);
if (*intptr == -1)
*intptr = value;
break;
case sLoginGraceTime:
intptr = &options->login_grace_time;
goto parse_int;
case sKeyRegenerationTime:
intptr = &options->key_regeneration_time;
goto parse_int;
case sListenAddress:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing inet addr.\n",
filename, linenum);
add_listen_addr(options, arg);
break;
case sHostKeyFile:
case sHostDSAKeyFile:
charptr = (opcode == sHostKeyFile ) ?
&options->host_key_file : &options->host_dsa_key_file;
parse_filename:
arg = strdelim(&cp);
if (!arg || *arg == '\0') {
fprintf(stderr, "%s line %d: missing file name.\n",
filename, linenum);
exit(1);
}
if (*charptr == NULL)
*charptr = tilde_expand_filename(arg, getuid());
break;
case sPidFile:
charptr = &options->pid_file;
goto parse_filename;
case sRandomSeedFile:
fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
filename, linenum);
arg = strdelim(&cp);
break;
case sPermitRootLogin:
intptr = &options->permit_root_login;
arg = strdelim(&cp);
if (!arg || *arg == '\0') {
fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
filename, linenum);
exit(1);
}
if (strcmp(arg, "without-password") == 0)
value = 2;
else if (strcmp(arg, "yes") == 0)
value = 1;
else if (strcmp(arg, "no") == 0)
value = 0;
else {
fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
filename, linenum, arg);
exit(1);
}
if (*intptr == -1)
*intptr = value;
break;
case sIgnoreRhosts:
intptr = &options->ignore_rhosts;
parse_flag:
arg = strdelim(&cp);
if (!arg || *arg == '\0') {
fprintf(stderr, "%s line %d: missing yes/no argument.\n",
filename, linenum);
exit(1);
}
if (strcmp(arg, "yes") == 0)
value = 1;
else if (strcmp(arg, "no") == 0)
value = 0;
else {
fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
filename, linenum, arg);
exit(1);
}
if (*intptr == -1)
*intptr = value;
break;
case sIgnoreUserKnownHosts:
intptr = &options->ignore_user_known_hosts;
goto parse_flag;
case sRhostsAuthentication:
intptr = &options->rhosts_authentication;
goto parse_flag;
case sRhostsRSAAuthentication:
intptr = &options->rhosts_rsa_authentication;
goto parse_flag;
case sRSAAuthentication:
intptr = &options->rsa_authentication;
goto parse_flag;
case sDSAAuthentication:
intptr = &options->dsa_authentication;
goto parse_flag;
#ifdef KRB4
case sKerberosAuthentication:
intptr = &options->kerberos_authentication;
goto parse_flag;
case sKerberosOrLocalPasswd:
intptr = &options->kerberos_or_local_passwd;
goto parse_flag;
case sKerberosTicketCleanup:
intptr = &options->kerberos_ticket_cleanup;
goto parse_flag;
#endif
#ifdef AFS
case sKerberosTgtPassing:
intptr = &options->kerberos_tgt_passing;
goto parse_flag;
case sAFSTokenPassing:
intptr = &options->afs_token_passing;
goto parse_flag;
#endif
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
case sCheckMail:
intptr = &options->check_mail;
goto parse_flag;
#ifdef SKEY
case sSkeyAuthentication:
intptr = &options->skey_authentication;
goto parse_flag;
#endif
case sPrintMotd:
intptr = &options->print_motd;
goto parse_flag;
case sX11Forwarding:
intptr = &options->x11_forwarding;
goto parse_flag;
case sX11DisplayOffset:
intptr = &options->x11_display_offset;
goto parse_int;
case sXAuthLocation:
charptr = &options->xauth_location;
goto parse_filename;
case sStrictModes:
intptr = &options->strict_modes;
goto parse_flag;
case sKeepAlives:
intptr = &options->keepalives;
goto parse_flag;
case sEmptyPasswd:
intptr = &options->permit_empty_passwd;
goto parse_flag;
case sUseLogin:
intptr = &options->use_login;
goto parse_flag;
case sGatewayPorts:
intptr = &options->gateway_ports;
goto parse_flag;
case sLogFacility:
intptr = (int *) &options->log_facility;
arg = strdelim(&cp);
value = log_facility_number(arg);
if (value == (SyslogFacility) - 1)
fatal("%.200s line %d: unsupported log facility '%s'\n",
filename, linenum, arg ? arg : "<NONE>");
if (*intptr == -1)
*intptr = (SyslogFacility) value;
break;
case sLogLevel:
intptr = (int *) &options->log_level;
arg = strdelim(&cp);
value = log_level_number(arg);
if (value == (LogLevel) - 1)
fatal("%.200s line %d: unsupported log level '%s'\n",
filename, linenum, arg ? arg : "<NONE>");
if (*intptr == -1)
*intptr = (LogLevel) value;
break;
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_users >= MAX_ALLOW_USERS)
fatal("%s line %d: too many allow users.\n",
filename, linenum);
options->allow_users[options->num_allow_users++] = xstrdup(arg);
}
break;
case sDenyUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_deny_users >= MAX_DENY_USERS)
fatal( "%s line %d: too many deny users.\n",
filename, linenum);
options->deny_users[options->num_deny_users++] = xstrdup(arg);
}
break;
case sAllowGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
fatal("%s line %d: too many allow groups.\n",
filename, linenum);
options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
}
break;
case sDenyGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_deny_groups >= MAX_DENY_GROUPS)
fatal("%s line %d: too many deny groups.\n",
filename, linenum);
options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
}
break;
case sCiphers:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
if (!ciphers_valid(arg))
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->ciphers == NULL)
options->ciphers = xstrdup(arg);
break;
case sProtocol:
intptr = &options->protocol;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
value = proto_spec(arg);
if (value == SSH_PROTO_UNKNOWN)
fatal("%s line %d: Bad protocol spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*intptr == SSH_PROTO_UNKNOWN)
*intptr = value;
break;
case sSubsystem:
if(options->num_subsystems >= MAX_SUBSYSTEMS) {
fatal("%s line %d: too many subsystems defined.",
filename, linenum);
}
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem name.",
filename, linenum);
for (i = 0; i < options->num_subsystems; i++)
if(strcmp(arg, options->subsystem_name[i]) == 0)
fatal("%s line %d: Subsystem '%s' already defined.",
filename, linenum, arg);
options->subsystem_name[options->num_subsystems] = xstrdup(arg);
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem command.",
filename, linenum);
options->subsystem_command[options->num_subsystems] = xstrdup(arg);
options->num_subsystems++;
break;
case sMaxStartups:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing MaxStartups spec.",
filename, linenum);
if (sscanf(arg, "%d:%d:%d",
&options->max_startups_begin,
&options->max_startups_rate,
&options->max_startups) == 3) {
if (options->max_startups_begin >
options->max_startups ||
options->max_startups_rate > 100 ||
options->max_startups_rate < 1)
fatal("%s line %d: Illegal MaxStartups spec.",
filename, linenum);
break;
}
intptr = &options->max_startups;
goto parse_int;
default:
fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n",
filename, linenum, arg, opcode);
exit(1);
}
if ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
fprintf(stderr,
"%s line %d: garbage at end of line; \"%.200s\".\n",
filename, linenum, arg);
exit(1);
}
}
fclose(f);
if (bad_options > 0) {
fprintf(stderr, "%s: terminating, %d bad configuration options\n",
filename, bad_options);
exit(1);
}
}

123
crypto/dist/ssh/servconf.h vendored Normal file
View File

@ -0,0 +1,123 @@
/* $NetBSD: servconf.h,v 1.1.1.1 2000/09/28 22:10:16 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Definitions for server configuration data and for the functions reading it.
*
* 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".
*/
/* from OpenBSD: servconf.h,v 1.28 2000/09/07 20:27:53 deraadt Exp */
#ifndef SERVCONF_H
#define SERVCONF_H
#define MAX_PORTS 256 /* Max # ports. */
#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */
#define MAX_DENY_USERS 256 /* Max # users on deny list. */
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
typedef struct {
unsigned int num_ports;
unsigned int ports_from_cmdline;
u_short ports[MAX_PORTS]; /* Port number to listen on. */
char *listen_addr; /* Address on which the server listens. */
struct addrinfo *listen_addrs; /* Addresses on which the server listens. */
char *host_key_file; /* File containing host key. */
char *host_dsa_key_file; /* File containing dsa host key. */
char *pid_file; /* Where to put our pid */
int server_key_bits;/* Size of the server key. */
int login_grace_time; /* Disconnect if no auth in this time
* (sec). */
int key_regeneration_time; /* Server key lifetime (seconds). */
int permit_root_login; /* If true, permit root login. */
int ignore_rhosts; /* Ignore .rhosts and .shosts. */
int ignore_user_known_hosts; /* Ignore ~/.ssh/known_hosts
* for RhostsRsaAuth */
int print_motd; /* If true, print /etc/motd. */
int check_mail; /* If true, check for new mail. */
int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
int x11_display_offset; /* What DISPLAY number to start
* searching at */
char *xauth_location; /* Location of xauth program */
int strict_modes; /* If true, require string home dir modes. */
int keepalives; /* If true, set SO_KEEPALIVE. */
char *ciphers; /* Ciphers in order of preference. */
int protocol; /* Protocol in order of preference. */
int gateway_ports; /* If true, allow remote connects to forwarded ports. */
SyslogFacility log_facility; /* Facility for system logging. */
LogLevel log_level; /* Level for system logging. */
int rhosts_authentication; /* If true, permit rhosts
* authentication. */
int rhosts_rsa_authentication; /* If true, permit rhosts RSA
* authentication. */
int rsa_authentication; /* If true, permit RSA authentication. */
int dsa_authentication; /* If true, permit DSA authentication. */
#ifdef KRB4
int kerberos_authentication; /* If true, permit Kerberos
* authentication. */
int kerberos_or_local_passwd; /* If true, permit kerberos
* and any other password
* authentication mechanism,
* such as SecurID or
* /etc/passwd */
int kerberos_ticket_cleanup; /* If true, destroy ticket
* file on logout. */
#endif
#ifdef AFS
int kerberos_tgt_passing; /* If true, permit Kerberos tgt
* passing. */
int afs_token_passing; /* If true, permit AFS token passing. */
#endif
int password_authentication; /* If true, permit password
* authentication. */
#ifdef SKEY
int skey_authentication; /* If true, permit s/key
* authentication. */
#endif
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int use_login; /* If true, login(1) is used */
unsigned int num_allow_users;
char *allow_users[MAX_ALLOW_USERS];
unsigned int num_deny_users;
char *deny_users[MAX_DENY_USERS];
unsigned int num_allow_groups;
char *allow_groups[MAX_ALLOW_GROUPS];
unsigned int num_deny_groups;
char *deny_groups[MAX_DENY_GROUPS];
unsigned int num_subsystems;
char *subsystem_name[MAX_SUBSYSTEMS];
char *subsystem_command[MAX_SUBSYSTEMS];
int max_startups_begin;
int max_startups_rate;
int max_startups;
} ServerOptions;
/*
* Initializes the server options to special values that indicate that they
* have not yet been set.
*/
void initialize_server_options(ServerOptions * options);
/*
* Reads the server configuration file. This only sets the values for those
* options that have the special value indicating they have not been set.
*/
void read_server_config(ServerOptions * options, const char *filename);
/* Sets values for those values that have not yet been set. */
void fill_default_server_options(ServerOptions * options);
#endif /* SERVCONF_H */

875
crypto/dist/ssh/serverloop.c vendored Normal file
View File

@ -0,0 +1,875 @@
/* $NetBSD: serverloop.c,v 1.1.1.1 2000/09/28 22:10:20 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Server main loop for handling the interactive session.
*
* 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 support 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 <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: serverloop.c,v 1.1.1.1 2000/09/28 22:10:20 thorpej Exp $");
#endif
#include "includes.h"
#include "xmalloc.h"
#include "ssh.h"
#include "packet.h"
#include "buffer.h"
#include "servconf.h"
#include "pty.h"
#include "channels.h"
#include "compat.h"
#include "ssh2.h"
#include "session.h"
#include "dispatch.h"
#include "auth-options.h"
static Buffer stdin_buffer; /* Buffer for stdin data. */
static Buffer stdout_buffer; /* Buffer for stdout data. */
static Buffer stderr_buffer; /* Buffer for stderr data. */
static int fdin; /* Descriptor for stdin (for writing) */
static int fdout; /* Descriptor for stdout (for reading);
May be same number as fdin. */
static int fderr; /* Descriptor for stderr. May be -1. */
static long stdin_bytes = 0; /* Number of bytes written to stdin. */
static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */
static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */
static long fdout_bytes = 0; /* Number of stdout bytes read from program. */
static int stdin_eof = 0; /* EOF message received from client. */
static int fdout_eof = 0; /* EOF encountered reading from fdout. */
static int fderr_eof = 0; /* EOF encountered readung from fderr. */
static int connection_in; /* Connection to client (input). */
static int connection_out; /* Connection to client (output). */
static unsigned int buffer_high;/* "Soft" max buffer size. */
static int max_fd; /* Max file descriptor number for select(). */
/*
* This SIGCHLD kludge is used to detect when the child exits. The server
* will exit after that, as soon as forwarded connections have terminated.
*/
static pid_t child_pid; /* Pid of the child. */
static volatile int child_terminated; /* The child has terminated. */
static volatile int child_wait_status; /* Status from wait(). */
void server_init_dispatch(void);
static void
sigchld_handler(int sig)
{
int save_errno = errno;
pid_t wait_pid;
debug("Received SIGCHLD.");
wait_pid = wait((int *) &child_wait_status);
if (wait_pid != -1) {
if (wait_pid != child_pid)
error("Strange, got SIGCHLD and wait returned pid %d but child is %d",
wait_pid, child_pid);
if (WIFEXITED(child_wait_status) ||
WIFSIGNALED(child_wait_status))
child_terminated = 1;
}
signal(SIGCHLD, sigchld_handler);
errno = save_errno;
}
static void
sigchld_handler2(int sig)
{
int save_errno = errno;
debug("Received SIGCHLD.");
child_terminated = 1;
signal(SIGCHLD, sigchld_handler2);
errno = save_errno;
}
/*
* Make packets from buffered stderr data, and buffer it for sending
* to the client.
*/
static void
make_packets_from_stderr_data(void)
{
int len;
/* Send buffered stderr data to the client. */
while (buffer_len(&stderr_buffer) > 0 &&
packet_not_very_much_data_to_write()) {
len = buffer_len(&stderr_buffer);
if (packet_is_interactive()) {
if (len > 512)
len = 512;
} else {
/* Keep the packets at reasonable size. */
if (len > packet_get_maxsize())
len = packet_get_maxsize();
}
packet_start(SSH_SMSG_STDERR_DATA);
packet_put_string(buffer_ptr(&stderr_buffer), len);
packet_send();
buffer_consume(&stderr_buffer, len);
stderr_bytes += len;
}
}
/*
* Make packets from buffered stdout data, and buffer it for sending to the
* client.
*/
static void
make_packets_from_stdout_data(void)
{
int len;
/* Send buffered stdout data to the client. */
while (buffer_len(&stdout_buffer) > 0 &&
packet_not_very_much_data_to_write()) {
len = buffer_len(&stdout_buffer);
if (packet_is_interactive()) {
if (len > 512)
len = 512;
} else {
/* Keep the packets at reasonable size. */
if (len > packet_get_maxsize())
len = packet_get_maxsize();
}
packet_start(SSH_SMSG_STDOUT_DATA);
packet_put_string(buffer_ptr(&stdout_buffer), len);
packet_send();
buffer_consume(&stdout_buffer, len);
stdout_bytes += len;
}
}
/*
* Sleep in select() until we can do something. This will initialize the
* select masks. Upon return, the masks will indicate which descriptors
* have data or can accept data. Optionally, a maximum time can be specified
* for the duration of the wait (0 = infinite).
*/
static void
wait_until_can_do_something(fd_set * readset, fd_set * writeset,
unsigned int max_time_milliseconds)
{
struct timeval tv, *tvp;
int ret;
/* When select fails we restart from here. */
retry_select:
/* Initialize select() masks. */
FD_ZERO(readset);
FD_ZERO(writeset);
if (compat20) {
/* wrong: bad condition XXX */
if (channel_not_very_much_buffered_data())
FD_SET(connection_in, readset);
} else {
/*
* Read packets from the client unless we have too much
* buffered stdin or channel data.
*/
if (buffer_len(&stdin_buffer) < buffer_high &&
channel_not_very_much_buffered_data())
FD_SET(connection_in, readset);
/*
* If there is not too much data already buffered going to
* the client, try to get some more data from the program.
*/
if (packet_not_very_much_data_to_write()) {
if (!fdout_eof)
FD_SET(fdout, readset);
if (!fderr_eof)
FD_SET(fderr, readset);
}
/*
* If we have buffered data, try to write some of that data
* to the program.
*/
if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
FD_SET(fdin, writeset);
}
/* Set masks for channel descriptors. */
channel_prepare_select(readset, writeset);
/*
* If we have buffered packet data going to the client, mark that
* descriptor.
*/
if (packet_have_data_to_write())
FD_SET(connection_out, writeset);
/* Update the maximum descriptor number if appropriate. */
if (channel_max_fd() > max_fd)
max_fd = channel_max_fd();
/*
* If child has terminated and there is enough buffer space to read
* from it, then read as much as is available and exit.
*/
if (child_terminated && packet_not_very_much_data_to_write())
if (max_time_milliseconds == 0)
max_time_milliseconds = 100;
if (max_time_milliseconds == 0)
tvp = NULL;
else {
tv.tv_sec = max_time_milliseconds / 1000;
tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
tvp = &tv;
}
if (tvp!=NULL)
debug("tvp!=NULL kid %d mili %d", child_terminated, max_time_milliseconds);
/* Wait for something to happen, or the timeout to expire. */
ret = select(max_fd + 1, readset, writeset, NULL, tvp);
if (ret < 0) {
if (errno != EINTR)
error("select: %.100s", strerror(errno));
else
goto retry_select;
}
}
/*
* Processes input from the client and the program. Input data is stored
* in buffers and processed later.
*/
static void
process_input(fd_set * readset)
{
int len;
char buf[16384];
/* Read and buffer any input data from the client. */
if (FD_ISSET(connection_in, readset)) {
len = read(connection_in, buf, sizeof(buf));
if (len == 0) {
verbose("Connection closed by remote host.");
fatal_cleanup();
} else if (len < 0) {
if (errno != EINTR && errno != EAGAIN) {
verbose("Read error from remote host: %.100s", strerror(errno));
fatal_cleanup();
}
} else {
/* Buffer any received data. */
packet_process_incoming(buf, len);
}
}
if (compat20)
return;
/* Read and buffer any available stdout data from the program. */
if (!fdout_eof && FD_ISSET(fdout, readset)) {
len = read(fdout, buf, sizeof(buf));
if (len < 0 && (errno == EINTR || errno == EAGAIN)) {
/* do nothing */
} else if (len <= 0) {
fdout_eof = 1;
} else {
buffer_append(&stdout_buffer, buf, len);
fdout_bytes += len;
}
}
/* Read and buffer any available stderr data from the program. */
if (!fderr_eof && FD_ISSET(fderr, readset)) {
len = read(fderr, buf, sizeof(buf));
if (len < 0 && (errno == EINTR || errno == EAGAIN)) {
/* do nothing */
} else if (len <= 0) {
fderr_eof = 1;
} else {
buffer_append(&stderr_buffer, buf, len);
}
}
}
/*
* Sends data from internal buffers to client program stdin.
*/
static void
process_output(fd_set * writeset)
{
int len;
/* Write buffered data to program stdin. */
if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) {
len = write(fdin, buffer_ptr(&stdin_buffer),
buffer_len(&stdin_buffer));
if (len < 0 && (errno == EINTR || errno == EAGAIN)) {
/* do nothing */
} else if (len <= 0) {
#ifdef USE_PIPES
close(fdin);
#else
if (fdin != fdout)
close(fdin);
else
shutdown(fdin, SHUT_WR); /* We will no longer send. */
#endif
fdin = -1;
} else {
/* Successful write. Consume the data from the buffer. */
buffer_consume(&stdin_buffer, len);
/* Update the count of bytes written to the program. */
stdin_bytes += len;
}
}
/* Send any buffered packet data to the client. */
if (FD_ISSET(connection_out, writeset))
packet_write_poll();
}
/*
* Wait until all buffered output has been sent to the client.
* This is used when the program terminates.
*/
static void
drain_output(void)
{
/* Send any buffered stdout data to the client. */
if (buffer_len(&stdout_buffer) > 0) {
packet_start(SSH_SMSG_STDOUT_DATA);
packet_put_string(buffer_ptr(&stdout_buffer),
buffer_len(&stdout_buffer));
packet_send();
/* Update the count of sent bytes. */
stdout_bytes += buffer_len(&stdout_buffer);
}
/* Send any buffered stderr data to the client. */
if (buffer_len(&stderr_buffer) > 0) {
packet_start(SSH_SMSG_STDERR_DATA);
packet_put_string(buffer_ptr(&stderr_buffer),
buffer_len(&stderr_buffer));
packet_send();
/* Update the count of sent bytes. */
stderr_bytes += buffer_len(&stderr_buffer);
}
/* Wait until all buffered data has been written to the client. */
packet_write_wait();
}
static void
process_buffered_input_packets(void)
{
dispatch_run(DISPATCH_NONBLOCK, NULL, NULL);
}
/*
* Performs the interactive session. This handles data transmission between
* the client and the program. Note that the notion of stdin, stdout, and
* stderr in this function is sort of reversed: this function writes to
* stdin (of the child program), and reads from stdout and stderr (of the
* child program).
*/
void
server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
{
fd_set readset, writeset;
int wait_status; /* Status returned by wait(). */
pid_t wait_pid; /* pid returned by wait(). */
int waiting_termination = 0; /* Have displayed waiting close message. */
unsigned int max_time_milliseconds;
unsigned int previous_stdout_buffer_bytes;
unsigned int stdout_buffer_bytes;
int type;
debug("Entering interactive session.");
/* Initialize the SIGCHLD kludge. */
child_pid = pid;
child_terminated = 0;
signal(SIGCHLD, sigchld_handler);
/* Initialize our global variables. */
fdin = fdin_arg;
fdout = fdout_arg;
fderr = fderr_arg;
/* nonblocking IO */
set_nonblock(fdin);
set_nonblock(fdout);
/* we don't have stderr for interactive terminal sessions, see below */
if (fderr != -1)
set_nonblock(fderr);
connection_in = packet_get_connection_in();
connection_out = packet_get_connection_out();
previous_stdout_buffer_bytes = 0;
/* Set approximate I/O buffer size. */
if (packet_is_interactive())
buffer_high = 4096;
else
buffer_high = 64 * 1024;
/* Initialize max_fd to the maximum of the known file descriptors. */
max_fd = fdin;
if (fdout > max_fd)
max_fd = fdout;
if (fderr != -1 && fderr > max_fd)
max_fd = fderr;
if (connection_in > max_fd)
max_fd = connection_in;
if (connection_out > max_fd)
max_fd = connection_out;
/* Initialize Initialize buffers. */
buffer_init(&stdin_buffer);
buffer_init(&stdout_buffer);
buffer_init(&stderr_buffer);
/*
* If we have no separate fderr (which is the case when we have a pty
* - there we cannot make difference between data sent to stdout and
* stderr), indicate that we have seen an EOF from stderr. This way
* we don\'t need to check the descriptor everywhere.
*/
if (fderr == -1)
fderr_eof = 1;
server_init_dispatch();
/* Main loop of the server for the interactive session mode. */
for (;;) {
/* Process buffered packets from the client. */
process_buffered_input_packets();
/*
* If we have received eof, and there is no more pending
* input data, cause a real eof by closing fdin.
*/
if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
#ifdef USE_PIPES
close(fdin);
#else
if (fdin != fdout)
close(fdin);
else
shutdown(fdin, SHUT_WR); /* We will no longer send. */
#endif
fdin = -1;
}
/* Make packets from buffered stderr data to send to the client. */
make_packets_from_stderr_data();
/*
* Make packets from buffered stdout data to send to the
* client. If there is very little to send, this arranges to
* not send them now, but to wait a short while to see if we
* are getting more data. This is necessary, as some systems
* wake up readers from a pty after each separate character.
*/
max_time_milliseconds = 0;
stdout_buffer_bytes = buffer_len(&stdout_buffer);
if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
stdout_buffer_bytes != previous_stdout_buffer_bytes) {
/* try again after a while */
max_time_milliseconds = 10;
} else {
/* Send it now. */
make_packets_from_stdout_data();
}
previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
/* Send channel data to the client. */
if (packet_not_very_much_data_to_write())
channel_output_poll();
/*
* Bail out of the loop if the program has closed its output
* descriptors, and we have no more data to send to the
* client, and there is no pending buffered data.
*/
if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) {
if (!channel_still_open())
break;
if (!waiting_termination) {
const char *s = "Waiting for forwarded connections to terminate...\r\n";
char *cp;
waiting_termination = 1;
buffer_append(&stderr_buffer, s, strlen(s));
/* Display list of open channels. */
cp = channel_open_message();
buffer_append(&stderr_buffer, cp, strlen(cp));
xfree(cp);
}
}
/* Sleep in select() until we can do something. */
wait_until_can_do_something(&readset, &writeset,
max_time_milliseconds);
/* Process any channel events. */
channel_after_select(&readset, &writeset);
/* Process input from the client and from program stdout/stderr. */
process_input(&readset);
/* Process output to the client and to program stdin. */
process_output(&writeset);
}
/* Cleanup and termination code. */
/* Wait until all output has been sent to the client. */
drain_output();
debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
/* Free and clear the buffers. */
buffer_free(&stdin_buffer);
buffer_free(&stdout_buffer);
buffer_free(&stderr_buffer);
/* Close the file descriptors. */
if (fdout != -1)
close(fdout);
fdout = -1;
fdout_eof = 1;
if (fderr != -1)
close(fderr);
fderr = -1;
fderr_eof = 1;
if (fdin != -1)
close(fdin);
fdin = -1;
/* Stop listening for channels; this removes unix domain sockets. */
channel_stop_listening();
/* Wait for the child to exit. Get its exit status. */
wait_pid = wait(&wait_status);
if (wait_pid < 0) {
/*
* It is possible that the wait was handled by SIGCHLD
* handler. This may result in either: this call
* returning with EINTR, or: this call returning ECHILD.
*/
if (child_terminated)
wait_status = child_wait_status;
else
packet_disconnect("wait: %.100s", strerror(errno));
} else {
/* Check if it matches the process we forked. */
if (wait_pid != pid)
error("Strange, wait returned pid %d, expected %d",
wait_pid, pid);
}
/* We no longer want our SIGCHLD handler to be called. */
signal(SIGCHLD, SIG_DFL);
/* Check if it exited normally. */
if (WIFEXITED(wait_status)) {
/* Yes, normal exit. Get exit status and send it to the client. */
debug("Command exited with status %d.", WEXITSTATUS(wait_status));
packet_start(SSH_SMSG_EXITSTATUS);
packet_put_int(WEXITSTATUS(wait_status));
packet_send();
packet_write_wait();
/*
* Wait for exit confirmation. Note that there might be
* other packets coming before it; however, the program has
* already died so we just ignore them. The client is
* supposed to respond with the confirmation when it receives
* the exit status.
*/
do {
int plen;
type = packet_read(&plen);
}
while (type != SSH_CMSG_EXIT_CONFIRMATION);
debug("Received exit confirmation.");
return;
}
/* Check if the program terminated due to a signal. */
if (WIFSIGNALED(wait_status))
packet_disconnect("Command terminated on signal %d.",
WTERMSIG(wait_status));
/* Some weird exit cause. Just exit. */
packet_disconnect("wait returned status %04x.", wait_status);
/* NOTREACHED */
}
void
server_loop2(void)
{
fd_set readset, writeset;
int had_channel = 0;
int status;
pid_t pid;
debug("Entering interactive session for SSH2.");
signal(SIGCHLD, sigchld_handler2);
child_terminated = 0;
connection_in = packet_get_connection_in();
connection_out = packet_get_connection_out();
max_fd = connection_in;
if (connection_out > max_fd)
max_fd = connection_out;
server_init_dispatch();
for (;;) {
process_buffered_input_packets();
if (!had_channel && channel_still_open())
had_channel = 1;
if (had_channel && !channel_still_open()) {
debug("!channel_still_open.");
break;
}
if (packet_not_very_much_data_to_write())
channel_output_poll();
wait_until_can_do_something(&readset, &writeset, 0);
if (child_terminated) {
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
session_close_by_pid(pid, status);
child_terminated = 0;
}
channel_after_select(&readset, &writeset);
process_input(&readset);
process_output(&writeset);
}
signal(SIGCHLD, SIG_DFL);
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
session_close_by_pid(pid, status);
channel_stop_listening();
}
static void
server_input_stdin_data(int type, int plen, void *ctxt)
{
char *data;
unsigned int data_len;
/* Stdin data from the client. Append it to the buffer. */
/* Ignore any data if the client has closed stdin. */
if (fdin == -1)
return;
data = packet_get_string(&data_len);
packet_integrity_check(plen, (4 + data_len), type);
buffer_append(&stdin_buffer, data, data_len);
memset(data, 0, data_len);
xfree(data);
}
static void
server_input_eof(int type, int plen, void *ctxt)
{
/*
* Eof from the client. The stdin descriptor to the
* program will be closed when all buffered data has
* drained.
*/
debug("EOF received for stdin.");
packet_integrity_check(plen, 0, type);
stdin_eof = 1;
}
static void
server_input_window_size(int type, int plen, void *ctxt)
{
int row = packet_get_int();
int col = packet_get_int();
int xpixel = packet_get_int();
int ypixel = packet_get_int();
debug("Window change received.");
packet_integrity_check(plen, 4 * 4, type);
if (fdin != -1)
pty_change_window_size(fdin, row, col, xpixel, ypixel);
}
static int
input_direct_tcpip(void)
{
int sock;
char *target, *originator;
int target_port, originator_port;
target = packet_get_string(NULL);
target_port = packet_get_int();
originator = packet_get_string(NULL);
originator_port = packet_get_int();
packet_done();
debug("open direct-tcpip: from %s port %d to %s port %d",
originator, originator_port, target, target_port);
/* XXX check permission */
if (no_port_forwarding_flag) {
xfree(target);
xfree(originator);
return -1;
}
sock = channel_connect_to(target, target_port);
xfree(target);
xfree(originator);
if (sock < 0)
return -1;
return channel_new("direct-tcpip", SSH_CHANNEL_OPEN,
sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"));
}
static void
server_input_channel_open(int type, int plen, void *ctxt)
{
Channel *c = NULL;
char *ctype;
int id;
unsigned int len;
int rchan;
int rmaxpack;
int rwindow;
ctype = packet_get_string(&len);
rchan = packet_get_int();
rwindow = packet_get_int();
rmaxpack = packet_get_int();
debug("server_input_channel_open: ctype %s rchan %d win %d max %d",
ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "session") == 0) {
debug("open session");
packet_done();
/*
* A server session has no fd to read or write
* until a CHANNEL_REQUEST for a shell is made,
* so we set the type to SSH_CHANNEL_LARVAL.
* Additionally, a callback for handling all
* CHANNEL_REQUEST messages is registered.
*/
id = channel_new(ctype, SSH_CHANNEL_LARVAL,
-1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT,
0, xstrdup("server-session"));
if (session_open(id) == 1) {
channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST,
session_input_channel_req, (void *)0);
channel_register_cleanup(id, session_close_by_channel);
c = channel_lookup(id);
} else {
debug("session open failed, free channel %d", id);
channel_free(id);
}
} else if (strcmp(ctype, "direct-tcpip") == 0) {
id = input_direct_tcpip();
if (id >= 0)
c = channel_lookup(id);
}
if (c != NULL) {
debug("confirm %s", ctype);
c->remote_id = rchan;
c->remote_window = rwindow;
c->remote_maxpacket = rmaxpack;
packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
packet_put_int(c->remote_id);
packet_put_int(c->self);
packet_put_int(c->local_window);
packet_put_int(c->local_maxpacket);
packet_send();
} else {
debug("failure %s", ctype);
packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
packet_put_int(rchan);
packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
packet_put_cstring("bla bla");
packet_put_cstring("");
packet_send();
}
xfree(ctype);
}
static void
server_init_dispatch_20(void)
{
debug("server_init_dispatch_20");
dispatch_init(&dispatch_protocol_error);
dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
}
static void
server_init_dispatch_13(void)
{
debug("server_init_dispatch_13");
dispatch_init(NULL);
dispatch_set(SSH_CMSG_EOF, &server_input_eof);
dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data);
dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size);
dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
}
static void
server_init_dispatch_15(void)
{
server_init_dispatch_13();
debug("server_init_dispatch_15");
dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
}
void
server_init_dispatch()
{
if (compat20)
server_init_dispatch_20();
else if (compat13)
server_init_dispatch_13();
else
server_init_dispatch_15();
}

1635
crypto/dist/ssh/session.c vendored Normal file

File diff suppressed because it is too large Load Diff

40
crypto/dist/ssh/session.h vendored Normal file
View File

@ -0,0 +1,40 @@
/* $NetBSD: session.h,v 1.1.1.1 2000/09/28 22:10:23 thorpej Exp $ */
/*
* 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 SESSION_H
#define SESSION_H
/* SSH1 */
void do_authenticated(struct passwd * pw);
/* SSH2 */
void do_authenticated2(void);
int session_open(int id);
void session_input_channel_req(int id, void *arg);
void session_close_by_pid(pid_t pid, int status);
void session_close_by_channel(int id, void *arg);
#endif

59
crypto/dist/ssh/sftp-server.8 vendored Normal file
View File

@ -0,0 +1,59 @@
.\"
.\" $NetBSD: sftp-server.8,v 1.1.1.1 2000/09/28 22:10:23 thorpej Exp $
.\"
.\" 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.
.\"
.\" from OpenBSD: sftp-server.8,v 1.2 2000/09/07 20:27:53 deraadt Exp
.\"
.Dd August 30, 2000
.Dt SFTP-SERVER 8
.Os
.Sh NAME
.Nm sftp-server
.Nd SFTP server subsystem
.Sh SYNOPSIS
.Nm sftp-server
.Sh DESCRIPTION
.Nm
is a program that speaks the server side of SFTP protocol
to stdout and expects client requests from stdin.
.Nm
is not intended to be called directly, but from
.Xr sshd 8
using the
.Cm Subsystem
option.
See
.Xr sshd 8
for more information.
.Sh HISTORY
.Nm
first appeared in
.Nx 1.5 .
.Sh AUTHOR
Markus Friedl <markus@openbsd.org>
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-keygen 1 ,
.Xr sshd 8

1078
crypto/dist/ssh/sftp-server.c vendored Normal file

File diff suppressed because it is too large Load Diff

131
crypto/dist/ssh/ssh-add.1 vendored Normal file
View File

@ -0,0 +1,131 @@
.\" -*- nroff -*-
.\"
.\" $NetBSD: ssh-add.1,v 1.1.1.1 2000/09/28 22:10:25 thorpej Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
.\" All rights reserved
.\"
.\" Created: Sat Apr 22 23:55:14 1995 ylo
.\"
.\" 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) 1999,2000 Markus Friedl. All rights reserved.
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
.\" Copyright (c) 1999 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.
.\"
.Dd August 6, 2000
.Dt SSH-ADD 1
.Os
.Sh NAME
.Nm ssh-add
.Nd add RSA or DSA identities to the Secure Shell authentication agent
.Sh SYNOPSIS
.Nm ssh-add
.Op Fl lLdD
.Op Ar
.Sh DESCRIPTION
.Nm
adds RSA or DSA identities to the Secure Shell authentication agent,
.Xr ssh-agent 1 .
When run without arguments, it adds the file
.Pa $HOME/.ssh/identity .
Alternative file names can be given on the command line.
If any file requires a passphrase,
.Nm
asks for the passphrase from the user.
If
.Nm
was invoked from a tty, the Passphrase is read from the tty.
If
.Nm
was not invoked from a tty, the
.Ev DISPLAY
environment variable is consulted and, if set, an external
Passphrase prompting program is run on that display.
.Pp
The authentication agent must be running and must be an ancestor of
the current process for
.Nm
to work.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl l
Lists fingerprints of all identities currently represented by the agent.
.It Fl L
Lists public key parameters of all identities currently represented by
the agent.
.It Fl d
Instead of adding the identity, removes the identity from the agent.
.It Fl D
Deletes all identities from the agent.
.El
.Sh FILES
.Bl -tag -width "SSH_ASKPASS"
.It Pa $HOME/.ssh/identity
Contains the RSA authentication identity of the user.
This file should not be readable by anyone but the user.
Note that
.Nm
ignores this file if it is accessible by others.
It is possible to
specify a passphrase when generating the key; that passphrase will be
used to encrypt the private part of this file.
This is the default identity added by
.Nm
when no other files have been specified.
.It Pa $HOME/.ssh/id_dsa
Contains the DSA authentication identity of the user.
.Pp
.El
.Sh ENVIRONMENT
.Bl -tag -width "SSH_ASKPASS"
.It Ev DISPLAY
If set, indicates the X11 display associated with a session. This
is the display that the external Passphrase prompting program will
be run on.
.It Ev SSH_ASKPASS
If set, indicates the program to use as the external Passphrase
prompter. If unset,
.Nm
will use the default
.Pa /usr/X11R6/bin/ssh-askpass .
This environment variable is useful for selecting Passphrase prompters
that are part of integrated desktop environments, such as
.Em GNOME
or
.Em KDE .
.El
.Sh AUTHOR
Tatu Ylonen <ylo@cs.hut.fi>, Markus Friedl
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
.Xr sshd 8

314
crypto/dist/ssh/ssh-add.c vendored Normal file
View File

@ -0,0 +1,314 @@
/* $NetBSD: ssh-add.c,v 1.1.1.1 2000/09/28 22:10:26 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Adds an identity to the authentication server, or removes an identity.
*
* 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.
*/
/* from OpenBSD: ssh-add.c,v 1.22 2000/09/07 20:27:54 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: ssh-add.c,v 1.1.1.1 2000/09/28 22:10:26 thorpej Exp $");
#endif
#include "includes.h"
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include "rsa.h"
#include "ssh.h"
#include "pathnames.h"
#include "xmalloc.h"
#include "key.h"
#include "authfd.h"
#include "authfile.h"
static void
delete_file(AuthenticationConnection *ac, const char *filename)
{
Key *public;
char *comment;
public = key_new(KEY_RSA);
if (!load_public_key(filename, public, &comment)) {
key_free(public);
public = key_new(KEY_DSA);
if (!try_load_public_key(filename, public, &comment)) {
printf("Bad key file %s\n", filename);
return;
}
}
if (ssh_remove_identity(ac, public))
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
else
fprintf(stderr, "Could not remove identity: %s\n", filename);
key_free(public);
xfree(comment);
}
/* Send a request to remove all identities. */
static void
delete_all(AuthenticationConnection *ac)
{
int success = 1;
if (!ssh_remove_all_identities(ac, 1))
success = 0;
/* ignore error-code for ssh2 */
ssh_remove_all_identities(ac, 2);
if (success)
fprintf(stderr, "All identities removed.\n");
else
fprintf(stderr, "Failed to remove all identitities.\n");
}
static char *
ssh_askpass(const char *askpass, char *msg)
{
pid_t pid;
size_t len;
char *nl, *pass;
int p[2], status;
char buf[1024];
if (askpass == NULL)
fatal("internal error: askpass undefined");
if (pipe(p) < 0)
fatal("ssh_askpass: pipe: %s", strerror(errno));
if ((pid = fork()) < 0)
fatal("ssh_askpass: fork: %s", strerror(errno));
if (pid == 0) {
close(p[0]);
if (dup2(p[1], STDOUT_FILENO) < 0)
fatal("ssh_askpass: dup2: %s", strerror(errno));
execlp(askpass, askpass, msg, (char *) 0);
fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno));
}
close(p[1]);
len = read(p[0], buf, sizeof buf);
close(p[0]);
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR)
break;
if (len <= 1)
return xstrdup("");
nl = strchr(buf, '\n');
if (nl)
*nl = '\0';
pass = xstrdup(buf);
memset(buf, 0, sizeof(buf));
return pass;
}
static void
add_file(AuthenticationConnection *ac, const char *filename)
{
struct stat st;
Key *public;
Key *private;
char *saved_comment, *comment;
const char *askpass = NULL;
char buf[1024], msg[1024];
int success;
int interactive = isatty(STDIN_FILENO);
int type = KEY_RSA;
int count;
if (stat(filename, &st) < 0) {
perror(filename);
exit(1);
}
/*
* try to load the public key. right now this only works for RSA,
* since DSA keys are fully encrypted
*/
public = key_new(KEY_RSA);
if (!load_public_key(filename, public, &saved_comment)) {
/* ok, so we will asume this is a DSA key */
type = KEY_DSA;
saved_comment = xstrdup(filename);
}
key_free(public);
if (!interactive && getenv("DISPLAY")) {
if (getenv(SSH_ASKPASS_ENV))
askpass = getenv(SSH_ASKPASS_ENV);
else
askpass = _PATH_SSH_ASKPASS;
}
/* At first, try empty passphrase */
private = key_new(type);
success = load_private_key(filename, "", private, &comment);
if (!success) {
printf("Need passphrase for %.200s\n", filename);
if (!interactive && askpass == NULL) {
xfree(saved_comment);
return;
}
for (count = 0; ; count++) {
char *pass;
snprintf(msg, sizeof msg,
"%sEnter passphrase for %.200s",
count > 0 ?
"You entered the wrong passphrase. " : "",
saved_comment);
if (interactive) {
snprintf(buf, sizeof buf, "%s: ", msg);
pass = read_passphrase(buf, 1);
} else {
pass = ssh_askpass(askpass, msg);
}
if (strcmp(pass, "") == 0) {
xfree(pass);
xfree(saved_comment);
return;
}
success = load_private_key(filename, pass, private, &comment);
memset(pass, 0, strlen(pass));
xfree(pass);
if (success)
break;
}
}
xfree(comment);
if (ssh_add_identity(ac, private, saved_comment))
fprintf(stderr, "Identity added: %s (%s)\n", filename, saved_comment);
else
fprintf(stderr, "Could not add identity: %s\n", filename);
key_free(private);
xfree(saved_comment);
}
static void
list_identities(AuthenticationConnection *ac, int fp)
{
Key *key;
char *comment;
int had_identities = 0;
int version;
for (version = 1; version <= 2; version++) {
for (key = ssh_get_first_identity(ac, &comment, version);
key != NULL;
key = ssh_get_next_identity(ac, &comment, version)) {
had_identities = 1;
if (fp) {
printf("%d %s %s\n",
key_size(key), key_fingerprint(key), comment);
} else {
if (!key_write(key, stdout))
fprintf(stderr, "key_write failed");
fprintf(stdout, " %s\n", comment);
}
key_free(key);
xfree(comment);
}
}
if (!had_identities)
printf("The agent has no identities.\n");
}
int
main(int argc, char **argv)
{
AuthenticationConnection *ac = NULL;
struct passwd *pw;
char buf[1024];
int no_files = 1;
int i;
int deleting = 0;
/* check if RSA support exists */
if (rsa_alive() == 0) {
extern char *__progname;
fprintf(stderr,
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
__progname);
exit(1);
}
SSLeay_add_all_algorithms();
/* At first, get a connection to the authentication agent. */
ac = ssh_get_authentication_connection();
if (ac == NULL) {
fprintf(stderr, "Could not open a connection to your authentication agent.\n");
exit(1);
}
for (i = 1; i < argc; i++) {
if ((strcmp(argv[i], "-l") == 0) ||
(strcmp(argv[i], "-L") == 0)) {
list_identities(ac, argv[i][1] == 'l' ? 1 : 0);
/* Don't default-add/delete if -l. */
no_files = 0;
continue;
}
if (strcmp(argv[i], "-d") == 0) {
deleting = 1;
continue;
}
if (strcmp(argv[i], "-D") == 0) {
delete_all(ac);
no_files = 0;
continue;
}
no_files = 0;
if (deleting)
delete_file(ac, argv[i]);
else
add_file(ac, argv[i]);
}
if (no_files) {
pw = getpwuid(getuid());
if (!pw) {
fprintf(stderr, "No user found with uid %u\n",
(u_int)getuid());
ssh_close_authentication_connection(ac);
exit(1);
}
snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, _PATH_SSH_CLIENT_IDENTITY);
if (deleting)
delete_file(ac, buf);
else
add_file(ac, buf);
}
ssh_close_authentication_connection(ac);
exit(0);
}

208
crypto/dist/ssh/ssh-agent.1 vendored Normal file
View File

@ -0,0 +1,208 @@
.\"
.\" $NetBSD: ssh-agent.1,v 1.1.1.1 2000/09/28 22:10:27 thorpej 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) 1999,2000 Markus Friedl. All rights reserved.
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
.\" Copyright (c) 1999 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.
.\"
.\" from OpenBSD: ssh-agent.1,v 1.16 2000/09/07 20:27:54 deraadt Exp
.\"
.Dd August 6, 2000
.Dt SSH-AGENT 1
.Os
.Sh NAME
.Nm ssh-agent
.Nd authentication agent for the Secure Shell
.Sh SYNOPSIS
.Nm ssh-agent
.Op Fl c Li | Fl s
.Op Fl k
.Oo
.Ar command
.Op Ar args ...
.Oc
.Sh DESCRIPTION
.Nm
is a program to hold private keys used for public key (RSA or DSA)
authentication. It is intended to be started at the beginning of
an X Window System or login session.
.Nm
works by setting certain variables in the user's environment. Through
the use of these environment variables, the agent can be located
and automatically used for RSA authentication when logging in to
other hosts using
.Xr ssh 1 .
.Pp
A user generally one identity per
.Dq workstation ,
e.g. laptop or desktop computer, handheld device, etc. Use of
.Nm
on these workstations prevents having to store authentication
information on remote hosts, and prevents having to transmit
Passphrases over the network.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl c
Generate C-shell commands on
.Dv stdout .
This is the default if
.Ev SHELL
looks like it's a csh style of shell.
.It Fl s
Generate Bourne shell commands on
.Dv stdout .
This is the default if
.Ev SHELL
does not look like it's a csh style of shell.
.It Fl k
Kill the current agent (given by the
.Ev SSH_AGENT_PID
environment variable).
.El
.Pp
If a command line is given, it is executed as a sub-process of the agent.
When the command dies, so does the agent. If a command line is not given,
the agent will not automatically exit, and must be explicitly killed with
the
.Fl k
option when the session ends.
.Pp
The agent initially does not have any private keys.
Keys must added using
.Xr ssh-add 1 .
.Pp
There are two main ways to set up the agent:
.Bl -bullet
.It
Invoke
.Nm
with a command line. The command will be started with the
appropriate environment variables set to use the agent.
.It
Invoke
.Nm
without a command line, which causes
.Nm
to print shell commands which will set up the enviroment if
evaluated by the shell.
.Nm
will attempt to detect if you are running a
.Xr csh 1
or
.Xr sh 1
style shell, and generate the appropriate syntax. The
syntax can be forced with the
.Fl c
and
.Fl s
flags.
.El
.Pp
When the agent is started, a Unix-domain socket is created
and the name of this socket stored in the
.Ev SSH_AUTH_SOCK
environment variable.
The socket is made accessible only to the current user.
This method is easily abused by root or another instance of the same
user.
.Sh EXAMPLES
The following shows using the command line facility of
.Nm
to associate an agent with an X session started by
.Xr xinit 1 :
.Bd -literal -offset indent
#!/bin/sh -
#
# $HOME/.xinitrc
#
if [ -r $HOME/.ssh/identity ]; then
EXEC="exec ssh-agent"
else
EXEC="exec"
fi
# .xsession will perform the ssh-add to add the keys.
$EXEC $HOME/.xsession
.Ed
.Pp
The following shows using
.Nm
and
.Xr ssh-add 1
in an X session startup script:
.Bd -literal -offset indent
#!/bin/sh -
#
# $HOME/.xsession
#
if [ -f $HOME/.Xdefaults ]; then
xrdb -merge $HOME/.Xdefaults
fi
xsetroot -solid black
if [ -r $HOME/.ssh/identity ]; then
eval `ssh-agent`
ssh-add < /dev/null # ensure stdin is not a tty
if [ $? != 0 ]; then
# Failed to provide a Passphrase, bail out!
exit 1
fi
fi
# Start the window manager.
twm
# Kill the agent we started above.
if [ -n "$SSH_AGENT_PID" ]; then
ssh-agent -k
fi
.Ed
.Sh FILES
.Bl -tag -width Ds
.It Pa /tmp/ssh-XXXXXXXX/agent.<pid>
Unix-domain sockets used to communicate with the
authentication agent. These sockets should only be readable by the
owner. The sockets should get automatically removed when the agent
exits.
.El
.Sh AUTHOR
Tatu Ylonen <ylo@cs.hut.fi>, Markus Friedl
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-keygen 1 ,
.Xr sshd 8

829
crypto/dist/ssh/ssh-agent.c vendored Normal file
View File

@ -0,0 +1,829 @@
/* $NetBSD: ssh-agent.c,v 1.1.1.1 2000/09/28 22:10:29 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* The authentication agent program.
*
* 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.
*/
/* from OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: ssh-agent.c,v 1.1.1.1 2000/09/28 22:10:29 thorpej Exp $");
#endif
#include "includes.h"
#include "ssh.h"
#include "rsa.h"
#include "buffer.h"
#include "bufaux.h"
#include "xmalloc.h"
#include "packet.h"
#include "pathnames.h"
#include "getput.h"
#include "mpaux.h"
#include <openssl/evp.h>
#include <openssl/md5.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include "key.h"
#include "authfd.h"
#include "dsa.h"
#include "kex.h"
#include "compat.h"
typedef struct {
int fd;
enum {
AUTH_UNUSED, AUTH_SOCKET, AUTH_CONNECTION
} type;
Buffer input;
Buffer output;
} SocketEntry;
unsigned int sockets_alloc = 0;
SocketEntry *sockets = NULL;
typedef struct {
Key *key;
char *comment;
} Identity;
typedef struct {
int nentries;
Identity *identities;
} Idtab;
/* private key table, one per protocol version */
Idtab idtable[3];
int max_fd = 0;
/* pid of shell == parent of agent */
pid_t parent_pid = -1;
/* pathname and directory for AUTH_SOCKET */
char socket_name[1024];
char socket_dir[1024];
extern char *__progname;
static void
idtab_init(void)
{
int i;
for (i = 0; i <=2; i++){
idtable[i].identities = NULL;
idtable[i].nentries = 0;
}
}
/* return private key table for requested protocol version */
static Idtab *
idtab_lookup(int version)
{
if (version < 1 || version > 2)
fatal("internal error, bad protocol version %d", version);
return &idtable[version];
}
/* return matching private key for given public key */
static Key *
lookup_private_key(Key *key, int *idx, int version)
{
int i;
Idtab *tab = idtab_lookup(version);
for (i = 0; i < tab->nentries; i++) {
if (key_equal(key, tab->identities[i].key)) {
if (idx != NULL)
*idx = i;
return tab->identities[i].key;
}
}
return NULL;
}
/* send list of supported public keys to 'client' */
static void
process_request_identities(SocketEntry *e, int version)
{
Idtab *tab = idtab_lookup(version);
Buffer msg;
int i;
buffer_init(&msg);
buffer_put_char(&msg, (version == 1) ?
SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
buffer_put_int(&msg, tab->nentries);
for (i = 0; i < tab->nentries; i++) {
Identity *id = &tab->identities[i];
if (id->key->type == KEY_RSA) {
buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
buffer_put_bignum(&msg, id->key->rsa->e);
buffer_put_bignum(&msg, id->key->rsa->n);
} else {
unsigned char *blob;
unsigned int blen;
dsa_make_key_blob(id->key, &blob, &blen);
buffer_put_string(&msg, blob, blen);
xfree(blob);
}
buffer_put_cstring(&msg, id->comment);
}
buffer_put_int(&e->output, buffer_len(&msg));
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
buffer_free(&msg);
}
/* ssh1 only */
static void
process_authentication_challenge1(SocketEntry *e)
{
Key *key, *private;
BIGNUM *challenge;
int i, len;
Buffer msg;
MD5_CTX md;
unsigned char buf[32], mdbuf[16], session_id[16];
unsigned int response_type;
buffer_init(&msg);
key = key_new(KEY_RSA);
challenge = BN_new();
buffer_get_int(&e->input); /* ignored */
buffer_get_bignum(&e->input, key->rsa->e);
buffer_get_bignum(&e->input, key->rsa->n);
buffer_get_bignum(&e->input, challenge);
/* Only protocol 1.1 is supported */
if (buffer_len(&e->input) == 0)
goto failure;
buffer_get(&e->input, (char *) session_id, 16);
response_type = buffer_get_int(&e->input);
if (response_type != 1)
goto failure;
private = lookup_private_key(key, NULL, 1);
if (private != NULL) {
/* Decrypt the challenge using the private key. */
rsa_private_decrypt(challenge, challenge, private->rsa);
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32) {
log("process_authentication_challenge: bad challenge length %d", len);
goto failure;
}
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
/* Send the response. */
buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
for (i = 0; i < 16; i++)
buffer_put_char(&msg, mdbuf[i]);
goto send;
}
failure:
/* Unknown identity or protocol error. Send failure. */
buffer_put_char(&msg, SSH_AGENT_FAILURE);
send:
buffer_put_int(&e->output, buffer_len(&msg));
buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
key_free(key);
BN_clear_free(challenge);
buffer_free(&msg);
}
/* ssh2 only */
static void
process_sign_request2(SocketEntry *e)
{
extern int datafellows;
Key *key, *private;
unsigned char *blob, *data, *signature = NULL;
unsigned int blen, dlen, slen = 0;
int flags;
Buffer msg;
int ok = -1;
datafellows = 0;
blob = buffer_get_string(&e->input, &blen);
data = buffer_get_string(&e->input, &dlen);
flags = buffer_get_int(&e->input);
if (flags & SSH_AGENT_OLD_SIGNATURE)
datafellows = SSH_BUG_SIGBLOB;
key = dsa_key_from_blob(blob, blen);
if (key != NULL) {
private = lookup_private_key(key, NULL, 2);
if (private != NULL)
ok = dsa_sign(private, &signature, &slen, data, dlen);
}
key_free(key);
buffer_init(&msg);
if (ok == 0) {
buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
buffer_put_string(&msg, signature, slen);
} else {
buffer_put_char(&msg, SSH_AGENT_FAILURE);
}
buffer_put_int(&e->output, buffer_len(&msg));
buffer_append(&e->output, buffer_ptr(&msg),
buffer_len(&msg));
buffer_free(&msg);
xfree(data);
xfree(blob);
if (signature != NULL)
xfree(signature);
}
/* shared */
static void
process_remove_identity(SocketEntry *e, int version)
{
Key *key = NULL, *private;
unsigned char *blob;
unsigned int blen;
unsigned int bits;
int success = 0;
switch(version){
case 1:
key = key_new(KEY_RSA);
bits = buffer_get_int(&e->input);
buffer_get_bignum(&e->input, key->rsa->e);
buffer_get_bignum(&e->input, key->rsa->n);
if (bits != key_size(key))
log("Warning: identity keysize mismatch: actual %d, announced %d",
key_size(key), bits);
break;
case 2:
blob = buffer_get_string(&e->input, &blen);
key = dsa_key_from_blob(blob, blen);
xfree(blob);
break;
}
if (key != NULL) {
int idx;
private = lookup_private_key(key, &idx, version);
if (private != NULL) {
/*
* We have this key. Free the old key. Since we
* don\'t want to leave empty slots in the middle of
* the array, we actually free the key there and copy
* data from the last entry.
*/
Idtab *tab = idtab_lookup(version);
key_free(tab->identities[idx].key);
xfree(tab->identities[idx].comment);
if (idx != tab->nentries)
tab->identities[idx] = tab->identities[tab->nentries];
tab->nentries--;
success = 1;
}
key_free(key);
}
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output,
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
}
static void
process_remove_all_identities(SocketEntry *e, int version)
{
unsigned int i;
Idtab *tab = idtab_lookup(version);
/* Loop over all identities and clear the keys. */
for (i = 0; i < tab->nentries; i++) {
key_free(tab->identities[i].key);
xfree(tab->identities[i].comment);
}
/* Mark that there are no identities. */
tab->nentries = 0;
/* Send success. */
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
return;
}
static void
process_add_identity(SocketEntry *e, int version)
{
Key *k = NULL;
RSA *rsa;
BIGNUM *aux;
BN_CTX *ctx;
char *type;
char *comment;
int success = 0;
Idtab *tab = idtab_lookup(version);
switch (version) {
case 1:
k = key_new(KEY_RSA);
rsa = k->rsa;
/* allocate mem for private key */
/* XXX rsa->n and rsa->e are already allocated */
rsa->d = BN_new();
rsa->iqmp = BN_new();
rsa->q = BN_new();
rsa->p = BN_new();
rsa->dmq1 = BN_new();
rsa->dmp1 = BN_new();
buffer_get_int(&e->input); /* ignored */
buffer_get_bignum(&e->input, rsa->n);
buffer_get_bignum(&e->input, rsa->e);
buffer_get_bignum(&e->input, rsa->d);
buffer_get_bignum(&e->input, rsa->iqmp);
/* SSH and SSL have p and q swapped */
buffer_get_bignum(&e->input, rsa->q); /* p */
buffer_get_bignum(&e->input, rsa->p); /* q */
/* Generate additional parameters */
aux = BN_new();
ctx = BN_CTX_new();
BN_sub(aux, rsa->q, BN_value_one());
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
BN_sub(aux, rsa->p, BN_value_one());
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
BN_clear_free(aux);
BN_CTX_free(ctx);
break;
case 2:
type = buffer_get_string(&e->input, NULL);
if (strcmp(type, KEX_DSS)) {
buffer_clear(&e->input);
xfree(type);
goto send;
}
xfree(type);
k = key_new(KEY_DSA);
/* allocate mem for private key */
k->dsa->priv_key = BN_new();
buffer_get_bignum2(&e->input, k->dsa->p);
buffer_get_bignum2(&e->input, k->dsa->q);
buffer_get_bignum2(&e->input, k->dsa->g);
buffer_get_bignum2(&e->input, k->dsa->pub_key);
buffer_get_bignum2(&e->input, k->dsa->priv_key);
break;
}
comment = buffer_get_string(&e->input, NULL);
if (k == NULL) {
xfree(comment);
goto send;
}
success = 1;
if (lookup_private_key(k, NULL, version) == NULL) {
if (tab->nentries == 0)
tab->identities = xmalloc(sizeof(Identity));
else
tab->identities = xrealloc(tab->identities,
(tab->nentries + 1) * sizeof(Identity));
tab->identities[tab->nentries].key = k;
tab->identities[tab->nentries].comment = comment;
/* Increment the number of identities. */
tab->nentries++;
} else {
key_free(k);
xfree(comment);
}
send:
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output,
success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
}
/* dispatch incoming messages */
static void
process_message(SocketEntry *e)
{
unsigned int msg_len;
unsigned int type;
unsigned char *cp;
if (buffer_len(&e->input) < 5)
return; /* Incomplete message. */
cp = (unsigned char *) buffer_ptr(&e->input);
msg_len = GET_32BIT(cp);
if (msg_len > 256 * 1024) {
shutdown(e->fd, SHUT_RDWR);
close(e->fd);
e->type = AUTH_UNUSED;
return;
}
if (buffer_len(&e->input) < msg_len + 4)
return;
buffer_consume(&e->input, 4);
type = buffer_get_char(&e->input);
switch (type) {
/* ssh1 */
case SSH_AGENTC_RSA_CHALLENGE:
process_authentication_challenge1(e);
break;
case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
process_request_identities(e, 1);
break;
case SSH_AGENTC_ADD_RSA_IDENTITY:
process_add_identity(e, 1);
break;
case SSH_AGENTC_REMOVE_RSA_IDENTITY:
process_remove_identity(e, 1);
break;
case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
process_remove_all_identities(e, 1);
break;
/* ssh2 */
case SSH2_AGENTC_SIGN_REQUEST:
process_sign_request2(e);
break;
case SSH2_AGENTC_REQUEST_IDENTITIES:
process_request_identities(e, 2);
break;
case SSH2_AGENTC_ADD_IDENTITY:
process_add_identity(e, 2);
break;
case SSH2_AGENTC_REMOVE_IDENTITY:
process_remove_identity(e, 2);
break;
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
process_remove_all_identities(e, 2);
break;
default:
/* Unknown message. Respond with failure. */
error("Unknown message %d", type);
buffer_clear(&e->input);
buffer_put_int(&e->output, 1);
buffer_put_char(&e->output, SSH_AGENT_FAILURE);
break;
}
}
static void
new_socket(int type, int fd)
{
unsigned int i, old_alloc;
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
error("fcntl O_NONBLOCK: %s", strerror(errno));
if (fd > max_fd)
max_fd = fd;
for (i = 0; i < sockets_alloc; i++)
if (sockets[i].type == AUTH_UNUSED) {
sockets[i].fd = fd;
sockets[i].type = type;
buffer_init(&sockets[i].input);
buffer_init(&sockets[i].output);
return;
}
old_alloc = sockets_alloc;
sockets_alloc += 10;
if (sockets)
sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0]));
else
sockets = xmalloc(sockets_alloc * sizeof(sockets[0]));
for (i = old_alloc; i < sockets_alloc; i++)
sockets[i].type = AUTH_UNUSED;
sockets[old_alloc].type = type;
sockets[old_alloc].fd = fd;
buffer_init(&sockets[old_alloc].input);
buffer_init(&sockets[old_alloc].output);
}
static void
prepare_select(fd_set *readset, fd_set *writeset)
{
unsigned int i;
for (i = 0; i < sockets_alloc; i++)
switch (sockets[i].type) {
case AUTH_SOCKET:
case AUTH_CONNECTION:
FD_SET(sockets[i].fd, readset);
if (buffer_len(&sockets[i].output) > 0)
FD_SET(sockets[i].fd, writeset);
break;
case AUTH_UNUSED:
break;
default:
fatal("Unknown socket type %d", sockets[i].type);
break;
}
}
static void
after_select(fd_set *readset, fd_set *writeset)
{
unsigned int i;
int len, sock;
socklen_t slen;
char buf[1024];
struct sockaddr_un sunaddr;
for (i = 0; i < sockets_alloc; i++)
switch (sockets[i].type) {
case AUTH_UNUSED:
break;
case AUTH_SOCKET:
if (FD_ISSET(sockets[i].fd, readset)) {
slen = sizeof(sunaddr);
sock = accept(sockets[i].fd, (struct sockaddr *) & sunaddr, &slen);
if (sock < 0) {
perror("accept from AUTH_SOCKET");
break;
}
new_socket(AUTH_CONNECTION, sock);
}
break;
case AUTH_CONNECTION:
if (buffer_len(&sockets[i].output) > 0 &&
FD_ISSET(sockets[i].fd, writeset)) {
len = write(sockets[i].fd, buffer_ptr(&sockets[i].output),
buffer_len(&sockets[i].output));
if (len <= 0) {
shutdown(sockets[i].fd, SHUT_RDWR);
close(sockets[i].fd);
sockets[i].type = AUTH_UNUSED;
buffer_free(&sockets[i].input);
buffer_free(&sockets[i].output);
break;
}
buffer_consume(&sockets[i].output, len);
}
if (FD_ISSET(sockets[i].fd, readset)) {
len = read(sockets[i].fd, buf, sizeof(buf));
if (len <= 0) {
shutdown(sockets[i].fd, SHUT_RDWR);
close(sockets[i].fd);
sockets[i].type = AUTH_UNUSED;
buffer_free(&sockets[i].input);
buffer_free(&sockets[i].output);
break;
}
buffer_append(&sockets[i].input, buf, len);
process_message(&sockets[i]);
}
break;
default:
fatal("Unknown type %d", sockets[i].type);
}
}
static void
check_parent_exists(int sig)
{
if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
/* printf("Parent has died - Authentication agent exiting.\n"); */
exit(1);
}
signal(SIGALRM, check_parent_exists);
alarm(10);
}
static void
cleanup_socket(void)
{
remove(socket_name);
rmdir(socket_dir);
}
static void
cleanup_exit(int i)
{
cleanup_socket();
exit(i);
}
static void
usage(void)
{
fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION);
fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n",
__progname);
exit(1);
}
int
main(int ac, char **av)
{
fd_set readset, writeset;
int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch;
struct sockaddr_un sunaddr;
pid_t pid;
char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
/* check if RSA support exists */
if (rsa_alive() == 0) {
fprintf(stderr,
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
__progname);
exit(1);
}
while ((ch = getopt(ac, av, "cks")) != -1) {
switch (ch) {
case 'c':
if (s_flag)
usage();
c_flag++;
break;
case 'k':
k_flag++;
break;
case 's':
if (c_flag)
usage();
s_flag++;
break;
default:
usage();
}
}
ac -= optind;
av += optind;
if (ac > 0 && (c_flag || k_flag || s_flag))
usage();
if (ac == 0 && !c_flag && !k_flag && !s_flag) {
shell = getenv("SHELL");
if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
c_flag = 1;
}
if (k_flag) {
pidstr = getenv(SSH_AGENTPID_ENV_NAME);
if (pidstr == NULL) {
fprintf(stderr, "%s not set, cannot kill agent\n",
SSH_AGENTPID_ENV_NAME);
exit(1);
}
pid = atoi(pidstr);
if (pid < 1) { /* XXX PID_MAX check too */
/* Yes, PID_MAX check please */
fprintf(stderr, "%s=\"%s\", which is not a good PID\n",
SSH_AGENTPID_ENV_NAME, pidstr);
exit(1);
}
if (kill(pid, SIGTERM) == -1) {
perror("kill");
exit(1);
}
format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME);
printf("echo Agent pid %d killed;\n", pid);
exit(0);
}
parent_pid = getpid();
/* Create private directory for agent socket */
strlcpy(socket_dir, _PATH_SSH_TMPDIR, sizeof socket_dir);
if (mkdtemp(socket_dir) == NULL) {
perror("mkdtemp: private socket dir");
exit(1);
}
snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
parent_pid);
/*
* Create socket early so it will exist before command gets run from
* the parent.
*/
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
cleanup_exit(1);
}
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
perror("bind");
cleanup_exit(1);
}
if (listen(sock, 5) < 0) {
perror("listen");
cleanup_exit(1);
}
/*
* Fork, and have the parent execute the command, if any, or present
* the socket data. The child continues as the authentication agent.
*/
pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid != 0) { /* Parent - execute the given command. */
close(sock);
snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
if (ac == 0) {
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
SSH_AGENTPID_ENV_NAME);
printf("echo Agent pid %d;\n", pid);
exit(0);
}
if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
perror("setenv");
exit(1);
}
execvp(av[0], av);
perror(av[0]);
exit(1);
}
close(0);
close(1);
close(2);
if (setsid() == -1) {
perror("setsid");
cleanup_exit(1);
}
if (atexit(cleanup_socket) < 0) {
perror("atexit");
cleanup_exit(1);
}
new_socket(AUTH_SOCKET, sock);
if (ac > 0) {
signal(SIGALRM, check_parent_exists);
alarm(10);
}
idtab_init();
signal(SIGINT, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, cleanup_exit);
signal(SIGTERM, cleanup_exit);
while (1) {
FD_ZERO(&readset);
FD_ZERO(&writeset);
prepare_select(&readset, &writeset);
if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0) {
if (errno == EINTR)
continue;
exit(1);
}
after_select(&readset, &writeset);
}
/* NOTREACHED */
}

221
crypto/dist/ssh/ssh-keygen.1 vendored Normal file
View File

@ -0,0 +1,221 @@
.\" -*- nroff -*-
.\"
.\" $NetBSD: ssh-keygen.1,v 1.1.1.1 2000/09/28 22:10:29 thorpej 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) 1999,2000 Markus Friedl. All rights reserved.
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
.\" Copyright (c) 1999 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.
.\"
.Dd August 6, 2000
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
.Nm ssh-keygen
.Nd generate Secure Shell authentication keys
.Sh SYNOPSIS
.Nm ssh-keygen
.Op Fl dq
.Op Fl b Ar bits
.Op Fl N Ar new_passphrase
.Op Fl C Ar comment
.Op Fl f Ar output_keyfile
.Nm ssh-keygen
.Fl p
.Op Fl P Ar old_passphrase
.Op Fl N Ar new_passphrase
.Op Fl f Ar keyfile
.Nm ssh-keygen
.Fl x
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl X
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl y
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl c
.Op Fl P Ar passphrase
.Op Fl C Ar comment
.Op Fl f Ar keyfile
.Nm ssh-keygen
.Fl l
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl R
.Sh DESCRIPTION
.Nm
generates and manages authentication keys for
.Xr ssh 1 .
.Nm
defaults to generating an RSA key for use by protocols 1.3 and 1.5;
specifying the
.Fl d
flag will create a DSA key for use by protocol 2.0.
.Pp
Normally each user wishing to use Secure Shell
with RSA or DSA authentication runs this once to create the
authentication key in
.Pa $HOME/.ssh/identity
or
.Pa $HOME/.ssh/id_dsa .
Additionally, the system administrator may use this to generate host keys;
An example of this can be found in the
.Xr sshd 8
startup script
.Pa /etc/rc.d/sshd .
.Pp
Normally this program generates the key and asks for a file in which
to store the private key.
The public key is stored in a file with the same name but
.Dq .pub
appended.
The program also asks for a passphrase.
The passphrase may be empty to indicate no passphrase
(host keys must have empty passphrase), or it may be a string of
arbitrary length.
Good passphrases are 10-30 characters long and are
not simple sentences or otherwise easily guessable (English
prose has only 1-2 bits of entropy per word, and makes very bad
passphrases).
The passphrase can be changed later by using the
.Fl p
option.
.Pp
There is no way to recover a lost passphrase. If the passphrase is
lost or forgotten, you will have to generate a new key and copy the
corresponding public key to other machines.
.Pp
For RSA, there is also a comment field in the key file that is only for
convenience to the user to help identify the key.
The comment can tell what the key is for, or whatever is useful.
The comment is initialized to
.Dq user@host
when the key is created, but can be changed using the
.Fl c
option.
.Pp
After a key is generated, instructions below detail where the keys
should be placed to be activated.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl b Ar bits
Specifies the number of bits in the key to create.
Minimum is 512 bits.
Generally 1024 bits is considered sufficient, and key sizes
above that no longer improve security but make things slower.
The default is 1024 bits.
.It Fl c
Requests changing the comment in the private and public key files.
The program will prompt for the file containing the private keys, for
passphrase if the key has one, and for the new comment.
.It Fl f
Specifies the filename of the key file.
.It Fl l
Show fingerprint of specified private or public key file.
.It Fl p
Requests changing the passphrase of a private key file instead of
creating a new private key.
The program will prompt for the file
containing the private key, for the old passphrase, and twice for the
new passphrase.
.It Fl q
Silence
.Nm ssh-keygen .
Used by
.Pa /etc/rc.d/sshd
when creating a new key.
.It Fl C Ar comment
Provides the new comment.
.It Fl N Ar new_passphrase
Provides the new passphrase.
.It Fl P Ar passphrase
Provides the (old) passphrase.
.It Fl R
If RSA support is functional, immediately exits with code 0. If RSA
support is not functional, exits with code 1. This flag will be
removed once the RSA patent expires.
.It Fl x
This option will read a private OpenSSH-compatible DSA format file and
print a SSH2-compatible public key to stdout.
.It Fl X
This option will read a SSH2-compatible public key file and print an
OpenSSH-compatible DSA public key to stdout.
.It Fl y
This option will read a private OpenSSH-compatible DSA format file and
print an OpenSSH-compatible DSA public key to stdout.
.El
.Sh FILES
.Bl -tag -width Ds
.It Pa $HOME/.ssh/identity
Contains the RSA authentication identity of the user.
This file should not be readable by anyone but the user.
It is possible to specify a passphrase when generating the key; that
passphrase will be used to encrypt the private part of this file using
3DES. This file is not automatically accessed by
.Nm
but it is offered as the default file for the private key.
.Xr sshd 8
will read this file when a login attempt is made.
.It Pa $HOME/.ssh/identity.pub
Contains the public key for authentication. The contents of this file
should be added to
.Pa $HOME/.ssh/authorized_keys
on all machines where you wish to log in using RSA authentication.
There is no need to keep the contents of this file secret.
.It Pa $HOME/.ssh/id_dsa
Contains the DSA authentication identity of the user. This file
should not be readable by anyone but the user. It is possible to
specify a passphrase when generating the key; that passphrase will be
used to encrypt the private part of this file using 3DES.
This file is not automatically accessed by
.Nm
but it is offered as the default file for the private key.
.Xr sshd 8
will read this file when a login attempt is made.
.It Pa $HOME/.ssh/id_dsa.pub
Contains the public key for authentication. The contents of this
file should be added to
.Pa $HOME/.ssh/authorized_keys2
on all machines where you wish to log in using DSA authentication.
There is no need to keep the contents of this file secret.
.El
.Sh AUTHOR
Tatu Ylonen <ylo@cs.hut.fi>
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
.Xr sshd 8

755
crypto/dist/ssh/ssh-keygen.c vendored Normal file
View File

@ -0,0 +1,755 @@
/* $NetBSD: ssh-keygen.c,v 1.1.1.1 2000/09/28 22:10:30 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Identity and host key generation and maintenance.
*
* 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".
*/
/* from OpenBSD: ssh-keygen.c,v 1.31 2000/09/07 20:27:54 deraadt Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: ssh-keygen.c,v 1.1.1.1 2000/09/28 22:10:30 thorpej Exp $");
#endif
#include "includes.h"
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include "ssh.h"
#include "pathnames.h"
#include "xmalloc.h"
#include "key.h"
#include "rsa.h"
#include "dsa.h"
#include "authfile.h"
#include "uuencode.h"
/* Number of bits in the RSA/DSA key. This value can be changed on the command line. */
int bits = 1024;
/*
* Flag indicating that we just want to change the passphrase. This can be
* set on the command line.
*/
int change_passphrase = 0;
/*
* Flag indicating that we just want to change the comment. This can be set
* on the command line.
*/
int change_comment = 0;
int quiet = 0;
/* Flag indicating that we just want to see the key fingerprint */
int print_fingerprint = 0;
/* The identity file name, given on the command line or entered by the user. */
char identity_file[1024];
int have_identity = 0;
/* This is set to the passphrase if given on the command line. */
char *identity_passphrase = NULL;
/* This is set to the new passphrase if given on the command line. */
char *identity_new_passphrase = NULL;
/* This is set to the new comment if given on the command line. */
char *identity_comment = NULL;
/* Dump public key file in format used by real and the original SSH 2 */
int convert_to_ssh2 = 0;
int convert_from_ssh2 = 0;
int print_public = 0;
int dsa_mode = 0;
/* argv0 */
extern char *__progname;
char hostname[MAXHOSTNAMELEN];
static void
ask_filename(struct passwd *pw, const char *prompt)
{
char buf[1024];
snprintf(identity_file, sizeof(identity_file), "%s/%s",
pw->pw_dir,
dsa_mode ? _PATH_SSH_CLIENT_ID_DSA: _PATH_SSH_CLIENT_IDENTITY);
printf("%s (%s): ", prompt, identity_file);
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
exit(1);
if (strchr(buf, '\n'))
*strchr(buf, '\n') = 0;
if (strcmp(buf, "") != 0)
strlcpy(identity_file, buf, sizeof(identity_file));
have_identity = 1;
}
static int
try_load_key(char *filename, Key *k)
{
int success = 1;
if (!load_private_key(filename, "", k, NULL)) {
char *pass = read_passphrase("Enter passphrase: ", 1);
if (!load_private_key(filename, pass, k, NULL)) {
success = 0;
}
memset(pass, 0, strlen(pass));
xfree(pass);
}
return success;
}
#define SSH_COM_MAGIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
#define SSH_COM_MAGIC_END "---- END SSH2 PUBLIC KEY ----"
static void
do_convert_to_ssh2(struct passwd *pw)
{
Key *k;
int len;
unsigned char *blob;
struct stat st;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0) {
perror(identity_file);
exit(1);
}
k = key_new(KEY_DSA);
if (!try_load_key(identity_file, k)) {
fprintf(stderr, "load failed\n");
exit(1);
}
dsa_make_key_blob(k, &blob, &len);
fprintf(stdout, "%s\n", SSH_COM_MAGIC_BEGIN);
fprintf(stdout,
"Comment: \"%d-bit DSA, converted from openssh by %s@%s\"\n",
BN_num_bits(k->dsa->p),
pw->pw_name, hostname);
dump_base64(stdout, blob, len);
fprintf(stdout, "%s\n", SSH_COM_MAGIC_END);
key_free(k);
xfree(blob);
exit(0);
}
static void
do_convert_from_ssh2(struct passwd *pw)
{
Key *k;
int blen;
char line[1024], *p;
char blob[8096];
char encoded[8096];
struct stat st;
int escaped = 0;
FILE *fp;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0) {
perror(identity_file);
exit(1);
}
fp = fopen(identity_file, "r");
if (fp == NULL) {
perror(identity_file);
exit(1);
}
encoded[0] = '\0';
while (fgets(line, sizeof(line), fp)) {
if (!(p = strchr(line, '\n'))) {
fprintf(stderr, "input line too long.\n");
exit(1);
}
if (p > line && p[-1] == '\\')
escaped++;
if (strncmp(line, "----", 4) == 0 ||
strstr(line, ": ") != NULL) {
fprintf(stderr, "ignore: %s", line);
continue;
}
if (escaped) {
escaped--;
fprintf(stderr, "escaped: %s", line);
continue;
}
*p = '\0';
strlcat(encoded, line, sizeof(encoded));
}
blen = uudecode(encoded, (unsigned char *)blob, sizeof(blob));
if (blen < 0) {
fprintf(stderr, "uudecode failed.\n");
exit(1);
}
k = dsa_key_from_blob(blob, blen);
if (!key_write(k, stdout))
fprintf(stderr, "key_write failed");
key_free(k);
fprintf(stdout, "\n");
fclose(fp);
exit(0);
}
static void
do_print_public(struct passwd *pw)
{
Key *k;
int len;
unsigned char *blob;
struct stat st;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0) {
perror(identity_file);
exit(1);
}
k = key_new(KEY_DSA);
if (!try_load_key(identity_file, k)) {
fprintf(stderr, "load failed\n");
exit(1);
}
dsa_make_key_blob(k, &blob, &len);
if (!key_write(k, stdout))
fprintf(stderr, "key_write failed");
key_free(k);
xfree(blob);
fprintf(stdout, "\n");
exit(0);
}
static void
do_fingerprint(struct passwd *pw)
{
/* XXX RSA1 only */
FILE *f;
Key *public;
char *comment = NULL, *cp, *ep, line[16*1024];
int i, skip = 0, num = 1, invalid = 1;
unsigned int ignore;
struct stat st;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0) {
perror(identity_file);
exit(1);
}
public = key_new(KEY_RSA);
if (load_public_key(identity_file, public, &comment)) {
printf("%d %s %s\n", BN_num_bits(public->rsa->n),
key_fingerprint(public), comment);
key_free(public);
exit(0);
}
f = fopen(identity_file, "r");
if (f != NULL) {
while (fgets(line, sizeof(line), f)) {
i = strlen(line) - 1;
if (line[i] != '\n') {
error("line %d too long: %.40s...", num, line);
skip = 1;
continue;
}
num++;
if (skip) {
skip = 0;
continue;
}
line[i] = '\0';
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '\n' || *cp == '#')
continue ;
i = strtol(cp, &ep, 10);
if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
int quoted = 0;
comment = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
if (!*cp)
continue;
*cp++ = '\0';
}
ep = cp;
if (auth_rsa_read_key(&cp, &ignore, public->rsa->e, public->rsa->n)) {
invalid = 0;
comment = *cp ? cp : comment;
printf("%d %s %s\n", key_size(public),
key_fingerprint(public),
comment ? comment : "no comment");
}
}
fclose(f);
}
key_free(public);
if (invalid) {
printf("%s is not a valid key file.\n", identity_file);
exit(1);
}
exit(0);
}
/*
* Perform changing a passphrase. The argument is the passwd structure
* for the current user.
*/
static void
do_change_passphrase(struct passwd *pw)
{
char *comment;
char *old_passphrase, *passphrase1, *passphrase2;
struct stat st;
Key *private;
Key *public;
int type = dsa_mode ? KEY_DSA : KEY_RSA;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0) {
perror(identity_file);
exit(1);
}
if (type == KEY_RSA) {
/* XXX this works currently only for RSA */
public = key_new(type);
if (!load_public_key(identity_file, public, NULL)) {
printf("%s is not a valid key file.\n", identity_file);
exit(1);
}
/* Clear the public key since we are just about to load the whole file. */
key_free(public);
}
/* Try to load the file with empty passphrase. */
private = key_new(type);
if (!load_private_key(identity_file, "", private, &comment)) {
if (identity_passphrase)
old_passphrase = xstrdup(identity_passphrase);
else
old_passphrase = read_passphrase("Enter old passphrase: ", 1);
if (!load_private_key(identity_file, old_passphrase, private, &comment)) {
memset(old_passphrase, 0, strlen(old_passphrase));
xfree(old_passphrase);
printf("Bad passphrase.\n");
exit(1);
}
memset(old_passphrase, 0, strlen(old_passphrase));
xfree(old_passphrase);
}
printf("Key has comment '%s'\n", comment);
/* Ask the new passphrase (twice). */
if (identity_new_passphrase) {
passphrase1 = xstrdup(identity_new_passphrase);
passphrase2 = NULL;
} else {
passphrase1 =
read_passphrase("Enter new passphrase (empty for no passphrase): ", 1);
passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
/* Verify that they are the same. */
if (strcmp(passphrase1, passphrase2) != 0) {
memset(passphrase1, 0, strlen(passphrase1));
memset(passphrase2, 0, strlen(passphrase2));
xfree(passphrase1);
xfree(passphrase2);
printf("Pass phrases do not match. Try again.\n");
exit(1);
}
/* Destroy the other copy. */
memset(passphrase2, 0, strlen(passphrase2));
xfree(passphrase2);
}
/* Save the file using the new passphrase. */
if (!save_private_key(identity_file, passphrase1, private, comment)) {
printf("Saving the key failed: %s: %s.\n",
identity_file, strerror(errno));
memset(passphrase1, 0, strlen(passphrase1));
xfree(passphrase1);
key_free(private);
xfree(comment);
exit(1);
}
/* Destroy the passphrase and the copy of the key in memory. */
memset(passphrase1, 0, strlen(passphrase1));
xfree(passphrase1);
key_free(private); /* Destroys contents */
xfree(comment);
printf("Your identification has been saved with the new passphrase.\n");
exit(0);
}
/*
* Change the comment of a private key file.
*/
static void
do_change_comment(struct passwd *pw)
{
char new_comment[1024], *comment;
Key *private;
Key *public;
char *passphrase;
struct stat st;
FILE *f;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0) {
perror(identity_file);
exit(1);
}
/*
* Try to load the public key from the file the verify that it is
* readable and of the proper format.
*/
public = key_new(KEY_RSA);
if (!load_public_key(identity_file, public, NULL)) {
printf("%s is not a valid key file.\n", identity_file);
exit(1);
}
private = key_new(KEY_RSA);
if (load_private_key(identity_file, "", private, &comment))
passphrase = xstrdup("");
else {
if (identity_passphrase)
passphrase = xstrdup(identity_passphrase);
else if (identity_new_passphrase)
passphrase = xstrdup(identity_new_passphrase);
else
passphrase = read_passphrase("Enter passphrase: ", 1);
/* Try to load using the passphrase. */
if (!load_private_key(identity_file, passphrase, private, &comment)) {
memset(passphrase, 0, strlen(passphrase));
xfree(passphrase);
printf("Bad passphrase.\n");
exit(1);
}
}
printf("Key now has comment '%s'\n", comment);
if (identity_comment) {
strlcpy(new_comment, identity_comment, sizeof(new_comment));
} else {
printf("Enter new comment: ");
fflush(stdout);
if (!fgets(new_comment, sizeof(new_comment), stdin)) {
memset(passphrase, 0, strlen(passphrase));
key_free(private);
exit(1);
}
if (strchr(new_comment, '\n'))
*strchr(new_comment, '\n') = 0;
}
/* Save the file using the new passphrase. */
if (!save_private_key(identity_file, passphrase, private, new_comment)) {
printf("Saving the key failed: %s: %s.\n",
identity_file, strerror(errno));
memset(passphrase, 0, strlen(passphrase));
xfree(passphrase);
key_free(private);
xfree(comment);
exit(1);
}
memset(passphrase, 0, strlen(passphrase));
xfree(passphrase);
key_free(private);
strlcat(identity_file, ".pub", sizeof(identity_file));
f = fopen(identity_file, "w");
if (!f) {
printf("Could not save your public key in %s\n", identity_file);
exit(1);
}
if (!key_write(public, f))
fprintf(stderr, "write key failed");
key_free(public);
fprintf(f, " %s\n", new_comment);
fclose(f);
xfree(comment);
printf("The comment in your key file has been changed.\n");
exit(0);
}
static void
usage(void)
{
printf("Usage: %s [-lpqxXydc] [-b bits] [-f file] [-C comment] [-N new-pass] [-P pass]\n", __progname);
exit(1);
}
/*
* Main program for key management.
*/
int
main(int ac, char **av)
{
char dotsshdir[16 * 1024], comment[1024], *passphrase1, *passphrase2;
struct passwd *pw;
int opt;
struct stat st;
FILE *f;
Key *private;
Key *public;
extern int optind;
extern char *optarg;
SSLeay_add_all_algorithms();
/* we need this for the home * directory. */
pw = getpwuid(getuid());
if (!pw) {
printf("You don't exist, go away!\n");
exit(1);
}
if (gethostname(hostname, sizeof(hostname)) < 0) {
perror("gethostname");
exit(1);
}
while ((opt = getopt(ac, av, "dqpclRxXyb:f:P:N:C:")) != EOF) {
switch (opt) {
case 'b':
bits = atoi(optarg);
if (bits < 512 || bits > 32768) {
printf("Bits has bad value.\n");
exit(1);
}
break;
case 'l':
print_fingerprint = 1;
break;
case 'p':
change_passphrase = 1;
break;
case 'c':
change_comment = 1;
break;
case 'f':
strlcpy(identity_file, optarg, sizeof(identity_file));
have_identity = 1;
break;
case 'P':
identity_passphrase = optarg;
break;
case 'N':
identity_new_passphrase = optarg;
break;
case 'C':
identity_comment = optarg;
break;
case 'q':
quiet = 1;
break;
case 'R':
if (rsa_alive() == 0)
exit(1);
else
exit(0);
break;
case 'x':
convert_to_ssh2 = 1;
break;
case 'X':
convert_from_ssh2 = 1;
break;
case 'y':
print_public = 1;
break;
case 'd':
dsa_mode = 1;
break;
case '?':
default:
usage();
}
}
if (optind < ac) {
printf("Too many arguments.\n");
usage();
}
if (change_passphrase && change_comment) {
printf("Can only have one of -p and -c.\n");
usage();
}
/* check if RSA support is needed and exists */
if (dsa_mode == 0 && rsa_alive() == 0) {
fprintf(stderr,
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
__progname);
exit(1);
}
if (print_fingerprint)
do_fingerprint(pw);
if (change_passphrase)
do_change_passphrase(pw);
if (change_comment)
do_change_comment(pw);
if (convert_to_ssh2)
do_convert_to_ssh2(pw);
if (convert_from_ssh2)
do_convert_from_ssh2(pw);
if (print_public)
do_print_public(pw);
ssh_random_stir();
if (dsa_mode != 0) {
if (!quiet)
printf("Generating DSA parameter and key.\n");
public = private = dsa_generate_key(bits);
if (private == NULL) {
fprintf(stderr, "dsa_generate_keys failed");
exit(1);
}
} else {
if (quiet)
rsa_set_verbose(0);
/* Generate the rsa key pair. */
public = key_new(KEY_RSA);
private = key_new(KEY_RSA);
rsa_generate_key(private->rsa, public->rsa, bits);
}
if (!have_identity)
ask_filename(pw, "Enter file in which to save the key");
/* Create ~/.ssh directory if it doesn\'t already exist. */
snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR);
if (strstr(identity_file, dotsshdir) != NULL &&
stat(dotsshdir, &st) < 0) {
if (mkdir(dotsshdir, 0700) < 0)
error("Could not create directory '%s'.", dotsshdir);
else if (!quiet)
printf("Created directory '%s'.\n", dotsshdir);
}
/* If the file already exists, ask the user to confirm. */
if (stat(identity_file, &st) >= 0) {
char yesno[3];
printf("%s already exists.\n", identity_file);
printf("Overwrite (y/n)? ");
fflush(stdout);
if (fgets(yesno, sizeof(yesno), stdin) == NULL)
exit(1);
if (yesno[0] != 'y' && yesno[0] != 'Y')
exit(1);
}
/* Ask for a passphrase (twice). */
if (identity_passphrase)
passphrase1 = xstrdup(identity_passphrase);
else if (identity_new_passphrase)
passphrase1 = xstrdup(identity_new_passphrase);
else {
passphrase_again:
passphrase1 =
read_passphrase("Enter passphrase (empty for no passphrase): ", 1);
passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
if (strcmp(passphrase1, passphrase2) != 0) {
/* The passphrases do not match. Clear them and retry. */
memset(passphrase1, 0, strlen(passphrase1));
memset(passphrase2, 0, strlen(passphrase2));
xfree(passphrase1);
xfree(passphrase2);
printf("Passphrases do not match. Try again.\n");
goto passphrase_again;
}
/* Clear the other copy of the passphrase. */
memset(passphrase2, 0, strlen(passphrase2));
xfree(passphrase2);
}
if (identity_comment) {
strlcpy(comment, identity_comment, sizeof(comment));
} else {
/* Create default commend field for the passphrase. */
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
}
/* Save the key with the given passphrase and comment. */
if (!save_private_key(identity_file, passphrase1, private, comment)) {
printf("Saving the key failed: %s: %s.\n",
identity_file, strerror(errno));
memset(passphrase1, 0, strlen(passphrase1));
xfree(passphrase1);
exit(1);
}
/* Clear the passphrase. */
memset(passphrase1, 0, strlen(passphrase1));
xfree(passphrase1);
/* Clear the private key and the random number generator. */
if (private != public) {
key_free(private);
}
ssh_random_stir();
if (!quiet)
printf("Your identification has been saved in %s.\n", identity_file);
strlcat(identity_file, ".pub", sizeof(identity_file));
f = fopen(identity_file, "w");
if (!f) {
printf("Could not save your public key in %s\n", identity_file);
exit(1);
}
if (!key_write(public, f))
fprintf(stderr, "write key failed");
fprintf(f, " %s\n", comment);
fclose(f);
if (!quiet) {
printf("Your public key has been saved in %s.\n",
identity_file);
printf("The key fingerprint is:\n");
printf("%s %s\n", key_fingerprint(public), comment);
}
key_free(public);
exit(0);
}

1185
crypto/dist/ssh/ssh.1 vendored Normal file

File diff suppressed because it is too large Load Diff

1029
crypto/dist/ssh/ssh.c vendored Normal file

File diff suppressed because it is too large Load Diff

33
crypto/dist/ssh/ssh.conf vendored Normal file
View File

@ -0,0 +1,33 @@
# $NetBSD: ssh.conf,v 1.1.1.1 2000/09/28 22:10:34 thorpej Exp $
#
# This is ssh client systemwide configuration file. This file provides
# defaults for users, and the values can be changed in per-user configuration
# files or on the command line.
# Configuration data is parsed as follows:
# 1. command line options
# 2. user-specific file
# 3. system-wide file
# Any configuration value is only changed the first time it is set.
# Thus, host-specific definitions should be at the beginning of the
# configuration file, and defaults at the end.
# Site-wide defaults for various options
# Host *
# ForwardAgent yes
# ForwardX11 yes
# RhostsAuthentication yes
# RhostsRSAAuthentication yes
# RSAAuthentication yes
# PasswordAuthentication yes
# FallBackToRsh no
# UseRsh no
# BatchMode no
# CheckHostIP yes
# StrictHostKeyChecking no
# IdentityFile ~/.ssh/identity
# Port 22
# Protocol 2,1
# Cipher blowfish
# EscapeChar ~

461
crypto/dist/ssh/ssh.h vendored Normal file
View File

@ -0,0 +1,461 @@
/* $NetBSD: ssh.h,v 1.1.1.1 2000/09/28 22:10:34 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* Generic header file for ssh.
*
* 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".
*/
/* from OpenBSD: ssh.h,v 1.51 2000/09/12 20:53:10 markus Exp */
#ifndef SSH_H
#define SSH_H
#include "rsa.h"
#include "cipher.h"
/*
* XXX
* The default cipher used if IDEA is not supported by the remote host. It is
* recommended that this be one of the mandatory ciphers (DES, 3DES), though
* that is not required.
*/
#define SSH_FALLBACK_CIPHER SSH_CIPHER_3DES
/* Cipher used for encrypting authentication files. */
#define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES
/* Default port number. */
#define SSH_DEFAULT_PORT 22
/* Maximum number of TCP/IP ports forwarded per direction. */
#define SSH_MAX_FORWARDS_PER_DIRECTION 100
/*
* Maximum number of RSA authentication identity files that can be specified
* in configuration files or on the command line.
*/
#define SSH_MAX_IDENTITY_FILES 100
/*
* Major protocol version. Different version indicates major incompatiblity
* that prevents communication.
*
* Minor protocol version. Different version indicates minor incompatibility
* that does not prevent interoperation.
*/
#define PROTOCOL_MAJOR_1 1
#define PROTOCOL_MINOR_1 5
/* We support both SSH1 and SSH2 */
#define PROTOCOL_MAJOR_2 2
#define PROTOCOL_MINOR_2 0
/*
* Name for the service. The port named by this service overrides the
* default port if present.
*/
#define SSH_SERVICE_NAME "ssh"
/*
* Name of the environment variable containing the pathname of the
* authentication socket.
*/
#define SSH_AUTHSOCKET_ENV_NAME "SSH_AUTH_SOCK"
/*
* Name of the environment variable containing the pathname of the
* authentication socket.
*/
#define SSH_AGENTPID_ENV_NAME "SSH_AGENT_PID"
/*
* environment variable for overwriting the default ssh-askpass location
*/
#define SSH_ASKPASS_ENV "SSH_ASKPASS"
/*
* Force host key length and server key length to differ by at least this
* many bits. This is to make double encryption with rsaref work.
*/
#define SSH_KEY_BITS_RESERVED 128
/*
* Length of the session key in bytes. (Specified as 256 bits in the
* protocol.)
*/
#define SSH_SESSION_KEY_LENGTH 32
/* Name of Kerberos service for SSH to use. */
#define KRB4_SERVICE_NAME "rcmd"
/*
* Authentication methods. New types can be added, but old types should not
* be removed for compatibility. The maximum allowed value is 31.
*/
#define SSH_AUTH_RHOSTS 1
#define SSH_AUTH_RSA 2
#define SSH_AUTH_PASSWORD 3
#define SSH_AUTH_RHOSTS_RSA 4
#define SSH_AUTH_TIS 5
#define SSH_AUTH_KERBEROS 6
#define SSH_PASS_KERBEROS_TGT 7
/* 8 to 15 are reserved */
#define SSH_PASS_AFS_TOKEN 21
/* Protocol flags. These are bit masks. */
#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */
#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain host */
/*
* Definition of message types. New values can be added, but old values
* should not be removed or without careful consideration of the consequences
* for compatibility. The maximum value is 254; value 255 is reserved for
* future extension.
*/
/* Message name */ /* msg code */ /* arguments */
#define SSH_MSG_NONE 0 /* no message */
#define SSH_MSG_DISCONNECT 1 /* cause (string) */
#define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
#define SSH_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
#define SSH_CMSG_USER 4 /* user (string) */
#define SSH_CMSG_AUTH_RHOSTS 5 /* user (string) */
#define SSH_CMSG_AUTH_RSA 6 /* modulus (BIGNUM) */
#define SSH_SMSG_AUTH_RSA_CHALLENGE 7 /* int (BIGNUM) */
#define SSH_CMSG_AUTH_RSA_RESPONSE 8 /* int (BIGNUM) */
#define SSH_CMSG_AUTH_PASSWORD 9 /* pass (string) */
#define SSH_CMSG_REQUEST_PTY 10 /* TERM, tty modes */
#define SSH_CMSG_WINDOW_SIZE 11 /* row,col,xpix,ypix */
#define SSH_CMSG_EXEC_SHELL 12 /* */
#define SSH_CMSG_EXEC_CMD 13 /* cmd (string) */
#define SSH_SMSG_SUCCESS 14 /* */
#define SSH_SMSG_FAILURE 15 /* */
#define SSH_CMSG_STDIN_DATA 16 /* data (string) */
#define SSH_SMSG_STDOUT_DATA 17 /* data (string) */
#define SSH_SMSG_STDERR_DATA 18 /* data (string) */
#define SSH_CMSG_EOF 19 /* */
#define SSH_SMSG_EXITSTATUS 20 /* status (int) */
#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21 /* channel (int) */
#define SSH_MSG_CHANNEL_OPEN_FAILURE 22 /* channel (int) */
#define SSH_MSG_CHANNEL_DATA 23 /* ch,data (int,str) */
#define SSH_MSG_CHANNEL_CLOSE 24 /* channel (int) */
#define SSH_MSG_CHANNEL_CLOSE_CONFIRMATION 25 /* channel (int) */
/* SSH_CMSG_X11_REQUEST_FORWARDING 26 OBSOLETE */
#define SSH_SMSG_X11_OPEN 27 /* channel (int) */
#define SSH_CMSG_PORT_FORWARD_REQUEST 28 /* p,host,hp (i,s,i) */
#define SSH_MSG_PORT_OPEN 29 /* ch,h,p (i,s,i) */
#define SSH_CMSG_AGENT_REQUEST_FORWARDING 30 /* */
#define SSH_SMSG_AGENT_OPEN 31 /* port (int) */
#define SSH_MSG_IGNORE 32 /* string */
#define SSH_CMSG_EXIT_CONFIRMATION 33 /* */
#define SSH_CMSG_X11_REQUEST_FORWARDING 34 /* proto,data (s,s) */
#define SSH_CMSG_AUTH_RHOSTS_RSA 35 /* user,mod (s,mpi) */
#define SSH_MSG_DEBUG 36 /* string */
#define SSH_CMSG_REQUEST_COMPRESSION 37 /* level 1-9 (int) */
#define SSH_CMSG_MAX_PACKET_SIZE 38 /* size 4k-1024k
(int) */
/*
* The protocol defines this message as support for the
* TIS authentication server. However, we currently use
* it for s/key challenge/response.
* XXX We should bring this up on secsh. --thorpej
*/
#define SSH_CMSG_AUTH_TIS 39 /* */
#define SSH_SMSG_AUTH_TIS_CHALLENGE 40 /* challenge (string) */
#define SSH_CMSG_AUTH_TIS_RESPONSE 41 /* response (string) */
#define SSH_CMSG_AUTH_KERBEROS 42 /* (KTEXT) */
#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */
#define SSH_CMSG_HAVE_KERBEROS_TGT 44 /* credentials (s) */
/* Reserved for official extensions. */
#define SSH_CMSG_RESERVED_START 45
#define SSH_CMSG_RESERVED_END 63
#define SSH_CMSG_HAVE_AFS_TOKEN 65 /* token (s) */
/*------------ definitions for login.c -------------*/
/*
* Returns the time when the user last logged in. Returns 0 if the
* information is not available. This must be called before record_login.
* The host from which the user logged in is stored in buf.
*/
unsigned long
get_last_login_time(uid_t uid, const char *logname,
char *buf, unsigned int bufsize);
/*
* Records that the user has logged in. This does many things normally done
* by login(1).
*/
void
record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid,
const char *host, struct sockaddr *addr);
/*
* Records that the user has logged out. This does many thigs normally done
* by login(1) or init.
*/
void record_logout(pid_t pid, const char *ttyname);
/*------------ definitions for sshconnect.c ----------*/
/*
* Opens a TCP/IP connection to the remote server on the given host. If port
* is 0, the default port will be used. If anonymous is zero, a privileged
* port will be allocated to make the connection. This requires super-user
* privileges if anonymous is false. Connection_attempts specifies the
* maximum number of tries, one per second. This returns true on success,
* and zero on failure. If the connection is successful, this calls
* packet_set_connection for the connection.
*/
int
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
u_short port, int connection_attempts,
int anonymous, uid_t original_real_uid,
const char *proxy_command);
/*
* Starts a dialog with the server, and authenticates the current user on the
* server. This does not need any extra privileges. The basic connection to
* the server must already have been established before this is called. If
* login fails, this function prints an error and never returns. This
* initializes the random state, and leaves it initialized (it will also have
* references from the packet module).
*/
void
ssh_login(int host_key_valid, RSA * host_key, const char *host,
struct sockaddr * hostaddr, uid_t original_real_uid);
/*------------ Definitions for various authentication methods. -------*/
/*
* Tries to authenticate the user using the .rhosts file. Returns true if
* authentication succeeds. If ignore_rhosts is non-zero, this will not
* consider .rhosts and .shosts (/etc/hosts.equiv will still be used).
*/
int auth_rhosts(struct passwd * pw, const char *client_user);
/*
* Tries to authenticate the user using the .rhosts file and the host using
* its host key. Returns true if authentication succeeds.
*/
int
auth_rhosts_rsa(struct passwd * pw, const char *client_user, RSA* client_host_key);
/*
* Tries to authenticate the user using password. Returns true if
* authentication succeeds.
*/
int auth_password(struct passwd * pw, const char *password);
/*
* Performs the RSA authentication dialog with the client. This returns 0 if
* the client could not be authenticated, and 1 if authentication was
* successful. This may exit if there is a serious protocol violation.
*/
int auth_rsa(struct passwd * pw, BIGNUM * client_n);
/*
* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
* over the key. Skips any whitespace at the beginning and at end.
*/
int auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n);
/*
* Returns the name of the machine at the other end of the socket. The
* returned string should be freed by the caller.
*/
char *get_remote_hostname(int socket);
/*
* Return the canonical name of the host in the other side of the current
* connection (as returned by packet_get_connection). The host name is
* cached, so it is efficient to call this several times.
*/
const char *get_canonical_hostname(void);
/*
* Returns the remote IP address as an ascii string. The value need not be
* freed by the caller.
*/
const char *get_remote_ipaddr(void);
/* Returns the port number of the peer of the socket. */
int get_peer_port(int sock);
/* Returns the port number of the remote/local host. */
int get_remote_port(void);
int get_local_port(void);
/*
* Performs the RSA authentication challenge-response dialog with the client,
* and returns true (non-zero) if the client gave the correct answer to our
* challenge; returns zero if the client gives a wrong answer.
*/
int auth_rsa_challenge_dialog(RSA *pk);
/*
* Reads a passphrase from /dev/tty with echo turned off. Returns the
* passphrase (allocated with xmalloc). Exits if EOF is encountered. If
* from_stdin is true, the passphrase will be read from stdin instead.
*/
char *read_passphrase(const char *prompt, int from_stdin);
/*------------ Definitions for logging. -----------------------*/
/* Supported syslog facilities and levels. */
typedef enum {
SYSLOG_FACILITY_DAEMON,
SYSLOG_FACILITY_USER,
SYSLOG_FACILITY_AUTH,
SYSLOG_FACILITY_LOCAL0,
SYSLOG_FACILITY_LOCAL1,
SYSLOG_FACILITY_LOCAL2,
SYSLOG_FACILITY_LOCAL3,
SYSLOG_FACILITY_LOCAL4,
SYSLOG_FACILITY_LOCAL5,
SYSLOG_FACILITY_LOCAL6,
SYSLOG_FACILITY_LOCAL7
} 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
} LogLevel;
/* Initializes logging. */
void log_init(const char *av0, LogLevel level, SyslogFacility facility,
int on_stderr, int quiet_mode, int debug_mode);
/* Logging implementation, depending on server or client */
void do_log(LogLevel level, const char *fmt, va_list args);
/* name to facility/level */
SyslogFacility log_facility_number(const char *name);
LogLevel log_level_number(const char *name);
/* Output a message to syslog or stderr */
void fatal(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void error(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void log(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void verbose(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void debug2(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void debug3(const char *fmt,...) __attribute__((format(printf, 1, 2)));
/* same as fatal() but w/o logging */
void fatal_cleanup(void);
/*
* Registers a cleanup function to be called by fatal()/fatal_cleanup()
* before exiting. It is permissible to call fatal_remove_cleanup for the
* function itself from the function.
*/
void fatal_add_cleanup(void (*proc) (void *context), void *context);
/* Removes a cleanup function to be called at fatal(). */
void fatal_remove_cleanup(void (*proc) (void *context), void *context);
/* ---- misc */
/*
* Expands tildes in the file name. Returns data allocated by xmalloc.
* Warning: this calls getpw*.
*/
char *tilde_expand_filename(const char *filename, uid_t my_uid);
/* remove newline at end of string */
char *chop(char *s);
/* return next token in configuration line */
char *strdelim(char **s);
/* set filedescriptor to non-blocking */
void set_nonblock(int fd);
/*
* Performs the interactive session. This handles data transmission between
* the client and the program. Note that the notion of stdin, stdout, and
* stderr in this function is sort of reversed: this function writes to stdin
* (of the child program), and reads from stdout and stderr (of the child
* program).
*/
void server_loop(pid_t pid, int fdin, int fdout, int fderr);
void server_loop2(void);
/* Client side main loop for the interactive session. */
int client_loop(int have_pty, int escape_char, int id);
/* Linked list of custom environment strings (see auth-rsa.c). */
struct envstring {
struct envstring *next;
char *s;
};
/*
* `Atomic' read and write operations, to ensure that all the
* data makes it through a socket (handles signals, etc.).
*/
ssize_t atomic_read(int, void *, size_t);
ssize_t atomic_write(int, const void *, size_t);
/*
* Misc. random functions.
*/
void ssh_random_stir(void);
#ifdef KRB4
#include <krb.h>
/*
* Performs Kerberos v4 mutual authentication with the client. This returns 0
* if the client could not be authenticated, and 1 if authentication was
* successful. This may exit if there is a serious protocol violation.
*/
int auth_krb4(const char *server_user, KTEXT auth, char **client);
int krb4_init(uid_t uid);
void krb4_cleanup_proc(void *ignore);
int auth_krb4_password(struct passwd * pw, const char *password);
#ifdef AFS
#include <kafs.h>
/* Accept passed Kerberos v4 ticket-granting ticket and AFS tokens. */
int auth_kerberos_tgt(struct passwd * pw, const char *string);
int auth_afs_token(struct passwd * pw, const char *token_string);
int creds_to_radix(CREDENTIALS * creds, unsigned char *buf, size_t buflen);
int radix_to_creds(const char *buf, CREDENTIALS * creds);
#endif /* AFS */
#endif /* KRB4 */
#ifdef SKEY
#include <skey.h>
char *skey_fake_keyinfo(const char *username);
int auth_skey_password(struct passwd *pw, const char *password);
#endif /* SKEY */
/* AF_UNSPEC or AF_INET or AF_INET6 */
extern int IPv4or6;
#endif /* SSH_H */

139
crypto/dist/ssh/ssh2.h vendored Normal file
View File

@ -0,0 +1,139 @@
/* $NetBSD: ssh2.h,v 1.1.1.1 2000/09/28 22:10:34 thorpej Exp $ */
/*
* 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.
*/
/*
* draft-ietf-secsh-architecture-05.txt
*
* Transport layer protocol:
*
* 1-19 Transport layer generic (e.g. disconnect, ignore, debug,
* etc)
* 20-29 Algorithm negotiation
* 30-49 Key exchange method specific (numbers can be reused for
* different authentication methods)
*
* User authentication protocol:
*
* 50-59 User authentication generic
* 60-79 User authentication method specific (numbers can be reused
* for different authentication methods)
*
* Connection protocol:
*
* 80-89 Connection protocol generic
* 90-127 Channel related messages
*
* Reserved for client protocols:
*
* 128-191 Reserved
*
* Local extensions:
*
* 192-255 Local extensions
*/
/* from OpenBSD: ssh2.h,v 1.4 2000/09/07 20:27:54 deraadt Exp */
/* transport layer: generic */
#define SSH2_MSG_DISCONNECT 1
#define SSH2_MSG_IGNORE 2
#define SSH2_MSG_UNIMPLEMENTED 3
#define SSH2_MSG_DEBUG 4
#define SSH2_MSG_SERVICE_REQUEST 5
#define SSH2_MSG_SERVICE_ACCEPT 6
/* transport layer: alg negotiation */
#define SSH2_MSG_KEXINIT 20
#define SSH2_MSG_NEWKEYS 21
/* transport layer: kex specific messages, can be reused */
#define SSH2_MSG_KEXDH_INIT 30
#define SSH2_MSG_KEXDH_REPLY 31
/* user authentication: generic */
#define SSH2_MSG_USERAUTH_REQUEST 50
#define SSH2_MSG_USERAUTH_FAILURE 51
#define SSH2_MSG_USERAUTH_SUCCESS 52
#define SSH2_MSG_USERAUTH_BANNER 53
/* user authentication: method specific, can be reused */
#define SSH2_MSG_USERAUTH_PK_OK 60
#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60
#define SSH2_MSG_USERAUTH_INFO_REQUEST 60
#define SSH2_MSG_USERAUTH_INFO_RESPONSE 61
/* connection protocol: generic */
#define SSH2_MSG_GLOBAL_REQUEST 80
#define SSH2_MSG_REQUEST_SUCCESS 81
#define SSH2_MSG_REQUEST_FAILURE 82
/* channel related messages */
#define SSH2_MSG_CHANNEL_OPEN 90
#define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91
#define SSH2_MSG_CHANNEL_OPEN_FAILURE 92
#define SSH2_MSG_CHANNEL_WINDOW_ADJUST 93
#define SSH2_MSG_CHANNEL_DATA 94
#define SSH2_MSG_CHANNEL_EXTENDED_DATA 95
#define SSH2_MSG_CHANNEL_EOF 96
#define SSH2_MSG_CHANNEL_CLOSE 97
#define SSH2_MSG_CHANNEL_REQUEST 98
#define SSH2_MSG_CHANNEL_SUCCESS 99
#define SSH2_MSG_CHANNEL_FAILURE 100
/* disconnect reason code */
#define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1
#define SSH2_DISCONNECT_PROTOCOL_ERROR 2
#define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3
#define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4
#define SSH2_DISCONNECT_RESERVED 4
#define SSH2_DISCONNECT_MAC_ERROR 5
#define SSH2_DISCONNECT_COMPRESSION_ERROR 6
#define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE 7
#define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8
#define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9
#define SSH2_DISCONNECT_CONNECTION_LOST 10
#define SSH2_DISCONNECT_BY_APPLICATION 11
#define SSH2_DISCONNECT_TOO_MANY_CONNECTIONS 12
#define SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER 13
#define SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14
#define SSH2_DISCONNECT_ILLEGAL_USER_NAME 15
/* misc */
#define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1
#define SSH2_OPEN_CONNECT_FAILED 2
#define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE 3
#define SSH2_OPEN_RESOURCE_SHORTAGE 4
#define SSH2_EXTENDED_DATA_STDERR 1

704
crypto/dist/ssh/sshconnect.c vendored Normal file
View File

@ -0,0 +1,704 @@
/* $NetBSD: sshconnect.c,v 1.1.1.1 2000/09/28 22:10:36 thorpej Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Code to connect to a remote host, and to perform the client side of the
* login (authentication) dialog.
*
* 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".
*/
/* from OpenBSD: sshconnect.c,v 1.79 2000/09/17 15:52:51 markus Exp */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: sshconnect.c,v 1.1.1.1 2000/09/28 22:10:36 thorpej Exp $");
#endif
#include "includes.h"
#include <openssl/bn.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include "xmalloc.h"
#include "rsa.h"
#include "ssh.h"
#include "buffer.h"
#include "packet.h"
#include "uidswap.h"
#include "compat.h"
#include "readconf.h"
#include "key.h"
#include "sshconnect.h"
#include "hostfile.h"
char *client_version_string = NULL;
char *server_version_string = NULL;
extern Options options;
extern char *__progname;
/*
* Connect to the given ssh server using a proxy command.
*/
static int
ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid,
const char *proxy_command)
{
Buffer command;
const char *cp;
char *command_string;
int pin[2], pout[2];
pid_t pid;
char strport[NI_MAXSERV];
/* Convert the port number into a string. */
snprintf(strport, sizeof strport, "%hu", port);
/* Build the final command string in the buffer by making the
appropriate substitutions to the given proxy command. */
buffer_init(&command);
for (cp = proxy_command; *cp; cp++) {
if (cp[0] == '%' && cp[1] == '%') {
buffer_append(&command, "%", 1);
cp++;
continue;
}
if (cp[0] == '%' && cp[1] == 'h') {
buffer_append(&command, host, strlen(host));
cp++;
continue;
}
if (cp[0] == '%' && cp[1] == 'p') {
buffer_append(&command, strport, strlen(strport));
cp++;
continue;
}
buffer_append(&command, cp, 1);
}
buffer_append(&command, "\0", 1);
/* Get the final command string. */
command_string = buffer_ptr(&command);
/* Create pipes for communicating with the proxy. */
if (pipe(pin) < 0 || pipe(pout) < 0)
fatal("Could not create pipes to communicate with the proxy: %.100s",
strerror(errno));
debug("Executing proxy command: %.500s", command_string);
/* Fork and execute the proxy command. */
if ((pid = fork()) == 0) {
char *argv[10];
/* Child. Permanently give up superuser privileges. */
permanently_set_uid(original_real_uid);
/* Redirect stdin and stdout. */
close(pin[1]);
if (pin[0] != 0) {
if (dup2(pin[0], 0) < 0)
perror("dup2 stdin");
close(pin[0]);
}
close(pout[0]);
if (dup2(pout[1], 1) < 0)
perror("dup2 stdout");
/* Cannot be 1 because pin allocated two descriptors. */
close(pout[1]);
/* Stderr is left as it is so that error messages get
printed on the user's terminal. */
argv[0] = _PATH_BSHELL;
argv[1] = "-c";
argv[2] = command_string;
argv[3] = NULL;
/* Execute the proxy command. Note that we gave up any
extra privileges above. */
execv(_PATH_BSHELL, argv);
perror(_PATH_BSHELL);
exit(1);
}
/* Parent. */
if (pid < 0)
fatal("fork failed: %.100s", strerror(errno));
/* Close child side of the descriptors. */
close(pin[0]);
close(pout[1]);
/* Free the command name. */
buffer_free(&command);
/* Set the connection file descriptors. */
packet_set_connection(pout[0], pin[1]);
return 1;
}
/*
* Creates a (possibly privileged) socket for use as the ssh connection.
*/
static int
ssh_create_socket(uid_t original_real_uid, int privileged, int family)
{
int sock;
/*
* If we are running as root and want to connect to a privileged
* port, bind our own socket to a privileged port.
*/
if (privileged) {
int p = IPPORT_RESERVED - 1;
sock = rresvport_af(&p, family);
if (sock < 0)
error("rresvport: af=%d %.100s", family, strerror(errno));
else
debug("Allocated local port %d.", p);
} else {
/*
* Just create an ordinary socket on arbitrary port. We use
* the user's uid to create the socket.
*/
temporarily_use_uid(original_real_uid);
sock = socket(family, SOCK_STREAM, 0);
if (sock < 0)
error("socket: %.100s", strerror(errno));
restore_uid();
}
return sock;
}
/*
* Opens a TCP/IP connection to the remote server on the given host.
* The address of the remote host will be returned in hostaddr.
* If port is 0, the default port will be used. If anonymous is zero,
* a privileged port will be allocated to make the connection.
* This requires super-user privileges if anonymous is false.
* Connection_attempts specifies the maximum number of tries (one per
* second). If proxy_command is non-NULL, it specifies the command (with %h
* and %p substituted for host and port, respectively) to use to contact
* the daemon.
*/
int
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
u_short port, int connection_attempts,
int anonymous, uid_t original_real_uid,
const char *proxy_command)
{
int sock = -1, attempt;
struct servent *sp;
struct addrinfo hints, *ai, *aitop;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
int gaierr;
struct linger linger;
debug("ssh_connect: getuid %u geteuid %u anon %d",
(u_int) getuid(), (u_int) geteuid(), anonymous);
/* Get default port if port has not been set. */
if (port == 0) {
sp = getservbyname(SSH_SERVICE_NAME, "tcp");
if (sp)
port = ntohs(sp->s_port);
else
port = SSH_DEFAULT_PORT;
}
/* If a proxy command is given, connect using it. */
if (proxy_command != NULL)
return ssh_proxy_connect(host, port, original_real_uid, proxy_command);
/* No proxy command. */
memset(&hints, 0, sizeof(hints));
hints.ai_family = IPv4or6;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
fatal("%s: %.100s: %s", __progname, host,
gai_strerror(gaierr));
/*
* Try to connect several times. On some machines, the first time
* will sometimes fail. In general socket code appears to behave
* quite magically on many machines.
*/
for (attempt = 0; attempt < connection_attempts; attempt++) {
if (attempt > 0)
debug("Trying again...");
/* Loop through addresses for this host, and try each one in
sequence until the connection succeeds. */
for (ai = aitop; ai; ai = ai->ai_next) {
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
continue;
if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
ntop, sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
error("ssh_connect: getnameinfo failed");
continue;
}
debug("Connecting to %.200s [%.100s] port %s.",
host, ntop, strport);
/* Create a socket for connecting. */
sock = ssh_create_socket(original_real_uid,
!anonymous && geteuid() == 0 && port < IPPORT_RESERVED,
ai->ai_family);
if (sock < 0)
continue;
/* Connect to the host. We use the user's uid in the
* hope that it will help with tcp_wrappers showing
* the remote uid as root.
*/
temporarily_use_uid(original_real_uid);
if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) {
/* Successful connection. */
memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
restore_uid();
break;
} else {
debug("connect: %.100s", strerror(errno));
restore_uid();
/*
* Close the failed socket; there appear to
* be some problems when reusing a socket for
* which connect() has already returned an
* error.
*/
shutdown(sock, SHUT_RDWR);
close(sock);
}
}
if (ai)
break; /* Successful connection. */
/* Sleep a moment before retrying. */
sleep(1);
}
freeaddrinfo(aitop);
/* Return failure if we didn't get a successful connection. */
if (attempt >= connection_attempts)
return 0;
debug("Connection established.");
/*
* Set socket options. We would like the socket to disappear as soon
* as it has been closed for whatever reason.
*/
/* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
linger.l_onoff = 1;
linger.l_linger = 5;
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
/* Set the connection. */
packet_set_connection(sock, sock);
return 1;
}
/*
* Waits for the server identification string, and sends our own
* identification string.
*/
static void
ssh_exchange_identification(void)
{
char buf[256], remote_version[256]; /* must be same size! */
int remote_major, remote_minor, i, mismatch;
int connection_in = packet_get_connection_in();
int connection_out = packet_get_connection_out();
/* Read other side\'s version identification. */
for (;;) {
for (i = 0; i < sizeof(buf) - 1; i++) {
int len = atomic_read(connection_in, &buf[i], 1);
if (len < 0)
fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
if (len != 1)
fatal("ssh_exchange_identification: Connection closed by remote host");
if (buf[i] == '\r') {
buf[i] = '\n';
buf[i + 1] = 0;
continue; /**XXX wait for \n */
}
if (buf[i] == '\n') {
buf[i + 1] = 0;
break;
}
}
buf[sizeof(buf) - 1] = 0;
if (strncmp(buf, "SSH-", 4) == 0)
break;
debug("ssh_exchange_identification: %s", buf);
}
server_version_string = xstrdup(buf);
/*
* Check that the versions match. In future this might accept
* several versions and set appropriate flags to handle them.
*/
if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n",
&remote_major, &remote_minor, remote_version) != 3)
fatal("Bad remote protocol version identification: '%.100s'", buf);
debug("Remote protocol version %d.%d, remote software version %.100s",
remote_major, remote_minor, remote_version);
compat_datafellows(remote_version);
mismatch = 0;
switch(remote_major) {
case 1:
if (remote_minor == 99 &&
(options.protocol & SSH_PROTO_2) &&
!(options.protocol & SSH_PROTO_1_PREFERRED)) {
enable_compat20();
break;
}
if (!(options.protocol & SSH_PROTO_1)) {
mismatch = 1;
break;
}
if (remote_minor < 3) {
fatal("Remote machine has too old SSH software version.");
} else if (remote_minor == 3) {
/* We speak 1.3, too. */
enable_compat13();
if (options.forward_agent) {
log("Agent forwarding disabled for protocol 1.3");
options.forward_agent = 0;
}
}
break;
case 2:
if (options.protocol & SSH_PROTO_2) {
enable_compat20();
break;
}
/* FALLTHROUGH */
default:
mismatch = 1;
break;
}
if (mismatch)
fatal("Protocol major versions differ: %d vs. %d",
(options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
remote_major);
if (compat20)
packet_set_ssh2_format();
/* Send our own protocol version identification. */
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
compat20 ? PROTOCOL_MINOR_2 : PROTOCOL_MINOR_1,
SSH_VERSION);
if (atomic_write(connection_out, buf, strlen(buf)) != strlen(buf))
fatal("write: %.100s", strerror(errno));
client_version_string = xstrdup(buf);
chop(client_version_string);
chop(server_version_string);
debug("Local version string %.100s", client_version_string);
}
static int
read_yes_or_no(const char *prompt, int defval)
{
char buf[1024];
FILE *f;
int retval = -1;
if (isatty(0))
f = stdin;
else
f = fopen(_PATH_TTY, "rw");
if (f == NULL)
return 0;
fflush(stdout);
while (1) {
fprintf(stderr, "%s", prompt);
if (fgets(buf, sizeof(buf), f) == NULL) {
/* Print a newline (the prompt probably didn\'t have one). */
fprintf(stderr, "\n");
strlcpy(buf, "no", sizeof buf);
}
/* Remove newline from response. */
if (strchr(buf, '\n'))
*strchr(buf, '\n') = 0;
if (buf[0] == 0)
retval = defval;
if (strcmp(buf, "yes") == 0)
retval = 1;
else if (strcmp(buf, "no") == 0)
retval = 0;
else
fprintf(stderr, "Please type 'yes' or 'no'.\n");
if (retval != -1) {
if (f != stdin)
fclose(f);
return retval;
}
}
}
/*
* check whether the supplied host key is valid, return only if ok.
*/
void
check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
const char *user_hostfile, const char *system_hostfile)
{
Key *file_key;
char *type = key_type(host_key);
char *ip = NULL;
char hostline[1000], *hostp;
HostStatus host_status;
HostStatus ip_status;
int local = 0, host_ip_differ = 0;
char ntop[NI_MAXHOST];
/*
* Force accepting of the host key for loopback/localhost. The
* problem is that if the home directory is NFS-mounted to multiple
* machines, localhost will refer to a different machine in each of
* them, and the user will get bogus HOST_CHANGED warnings. This
* essentially disables host authentication for localhost; however,
* this is probably not a real problem.
*/
/** hostaddr == 0! */
switch (hostaddr->sa_family) {
case AF_INET:
local = (ntohl(((struct sockaddr_in *)hostaddr)->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
break;
case AF_INET6:
local = IN6_IS_ADDR_LOOPBACK(&(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
break;
default:
local = 0;
break;
}
if (local) {
debug("Forcing accepting of host key for loopback/localhost.");
return;
}
/*
* Turn off check_host_ip for proxy connects, since
* we don't have the remote ip-address
*/
if (options.proxy_command != NULL && options.check_host_ip)
options.check_host_ip = 0;
if (options.check_host_ip) {
if (getnameinfo(hostaddr, hostaddr->sa_len, ntop, sizeof(ntop),
NULL, 0, NI_NUMERICHOST) != 0)
fatal("check_host_key: getnameinfo failed");
ip = xstrdup(ntop);
}
/*
* Store the host key from the known host file in here so that we can
* compare it with the key for the IP address.
*/
file_key = key_new(host_key->type);
/*
* Check if the host key is present in the user\'s list of known
* hosts or in the systemwide list.
*/
host_status = check_host_in_hostfile(user_hostfile, host, host_key, file_key);
if (host_status == HOST_NEW)
host_status = check_host_in_hostfile(system_hostfile, host, host_key, file_key);
/*
* Also perform check for the ip address, skip the check if we are
* localhost or the hostname was an ip address to begin with
*/
if (options.check_host_ip && !local && strcmp(host, ip)) {
Key *ip_key = key_new(host_key->type);
ip_status = check_host_in_hostfile(user_hostfile, ip, host_key, ip_key);
if (ip_status == HOST_NEW)
ip_status = check_host_in_hostfile(system_hostfile, ip, host_key, ip_key);
if (host_status == HOST_CHANGED &&
(ip_status != HOST_CHANGED || !key_equal(ip_key, file_key)))
host_ip_differ = 1;
key_free(ip_key);
} else
ip_status = host_status;
key_free(file_key);
switch (host_status) {
case HOST_OK:
/* The host is known and the key matches. */
debug("Host '%.200s' is known and matches the %s host key.",
host, type);
if (options.check_host_ip) {
if (ip_status == HOST_NEW) {
if (!add_host_to_hostfile(user_hostfile, ip, host_key))
log("Failed to add the %s host key for IP address '%.30s' to the list of known hosts (%.30s).",
type, ip, user_hostfile);
else
log("Warning: Permanently added the %s host key for IP address '%.30s' to the list of known hosts.",
type, ip);
} else if (ip_status != HOST_OK)
log("Warning: the %s host key for '%.200s' differs from the key for the IP address '%.30s'",
type, host, ip);
}
break;
case HOST_NEW:
/* The host is new. */
if (options.strict_host_key_checking == 1) {
/* User has requested strict host key checking. We will not add the host key
automatically. The only alternative left is to abort. */
fatal("No %s host key is known for %.200s and you have requested strict checking.", type, host);
} else if (options.strict_host_key_checking == 2) {
/* The default */
char prompt[1024];
char *fp = key_fingerprint(host_key);
snprintf(prompt, sizeof(prompt),
"The authenticity of host '%.200s' can't be established.\n"
"%s key fingerprint is %s.\n"
"Are you sure you want to continue connecting (yes/no)? ",
host, type, fp);
if (!read_yes_or_no(prompt, -1))
fatal("Aborted by user!\n");
}
if (options.check_host_ip && ip_status == HOST_NEW && strcmp(host, ip)) {
snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
hostp = hostline;
} else
hostp = host;
/* If not in strict mode, add the key automatically to the local known_hosts file. */
if (!add_host_to_hostfile(user_hostfile, hostp, host_key))
log("Failed to add the host to the list of known hosts (%.500s).",
user_hostfile);
else
log("Warning: Permanently added '%.200s' (%s) to the list of known hosts.",
hostp, type);
break;
case HOST_CHANGED:
if (options.check_host_ip && host_ip_differ) {
char *msg;
if (ip_status == HOST_NEW)
msg = "is unknown";
else if (ip_status == HOST_OK)
msg = "is unchanged";
else
msg = "has a different value";
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("The %s host key for %s has changed,", type, host);
error("and the key for the according IP address %s", ip);
error("%s. This could either mean that", msg);
error("DNS SPOOFING is happening or the IP address for the host");
error("and its host key have changed at the same time");
}
/* The host key has changed. */
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
error("It is also possible that the %s host key has just been changed.", type);
error("Please contact your system administrator.");
error("Add correct host key in %.100s to get rid of this message.",
user_hostfile);
/*
* If strict host key checking is in use, the user will have
* to edit the key manually and we can only abort.
*/
if (options.strict_host_key_checking)
fatal("%s host key for %.200s has changed and you have requested strict checking.", type, host);
/*
* If strict host key checking has not been requested, allow
* the connection but without password authentication or
* agent forwarding.
*/
if (options.password_authentication) {
error("Password authentication is disabled to avoid trojan horses.");
options.password_authentication = 0;
}
if (options.forward_agent) {
error("Agent forwarding is disabled to avoid trojan horses.");
options.forward_agent = 0;
}
/*
* XXX Should permit the user to change to use the new id.
* This could be done by converting the host key to an
* identifying sentence, tell that the host identifies itself
* by that sentence, and ask the user if he/she whishes to
* accept the authentication.
*/
break;
}
if (options.check_host_ip)
xfree(ip);
}
/*
* Starts a dialog with the server, and authenticates the current user on the
* server. This does not need any extra privileges. The basic connection
* to the server must already have been established before this is called.
* If login fails, this function prints an error and never returns.
* This function does not require super-user privileges.
*/
void
ssh_login(int host_key_valid, RSA *own_host_key, const char *orighost,
struct sockaddr *hostaddr, uid_t original_real_uid)
{
struct passwd *pw;
char *host, *cp;
char *server_user, *local_user;
/* Get local user name. Use it as server user if no user name was given. */
pw = getpwuid(original_real_uid);
if (!pw)
fatal("User id %u not found from user database.", original_real_uid);
local_user = xstrdup(pw->pw_name);
server_user = options.user ? options.user : local_user;
/* Convert the user-supplied hostname into all lowercase. */
host = xstrdup(orighost);
for (cp = host; *cp; cp++)
if (isupper(*cp))
*cp = tolower(*cp);
/* Exchange protocol version identification strings with the server. */
ssh_exchange_identification();
/* Put the connection into non-blocking mode. */
packet_set_nonblocking();
/* key exchange */
/* authenticate user */
if (compat20) {
ssh_kex2(host, hostaddr);
ssh_userauth2(server_user, host);
} else {
ssh_kex(host, hostaddr);
ssh_userauth(local_user, server_user, host, host_key_valid, own_host_key);
}
}

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