Upgrade to OpenSSH 7.6p1. This will be followed shortly by 7.7p1.
This completely removes client-side support for the SSH 1 protocol, which was already disabled in 12 but is still enabled in 11. For that reason, we will not be able to merge 7.6p1 or newer back to 11.
This commit is contained in:
commit
4f52dfbb8d
28
crypto/openssh/.gitignore
vendored
Normal file
28
crypto/openssh/.gitignore
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
Makefile
|
||||
buildpkg.sh
|
||||
config.h
|
||||
config.h.in
|
||||
config.status
|
||||
configure
|
||||
openbsd-compat/Makefile
|
||||
openbsd-compat/regress/Makefile
|
||||
openssh.xml
|
||||
opensshd.init
|
||||
survey.sh
|
||||
**/*.0
|
||||
**/*.o
|
||||
**/*.out
|
||||
**/*.a
|
||||
autom4te.cache/
|
||||
scp
|
||||
sftp
|
||||
sftp-server
|
||||
ssh
|
||||
ssh-add
|
||||
ssh-agent
|
||||
ssh-keygen
|
||||
ssh-keyscan
|
||||
ssh-keysign
|
||||
ssh-pkcs11-helper
|
||||
sshd
|
||||
!regress/misc/fuzz-harness/Makefile
|
@ -11,3 +11,13 @@ f6ae971186ba68d066cd102e57d5b0b2c211a5ee systrace is dead.
|
||||
96c5054e3e1f170c6276902d5bc65bb3b87a2603 remove DEBUGLIBS from Makefile
|
||||
6da9a37f74aef9f9cc639004345ad893cad582d8 Update moduli file
|
||||
77bcb50e47b68c7209c7f0a5a020d73761e5143b unset REGRESS_FAIL_EARLY
|
||||
38c2133817cbcae75c88c63599ac54228f0fa384 Change COMPILER_VERSION tests
|
||||
30c20180c87cbc99fa1020489fe7fd8245b6420c resync integrity.sh shell
|
||||
1e6b51ddf767cbad0a4e63eb08026c127e654308 integrity.sh reliability
|
||||
fe5b31f69a60d47171836911f144acff77810217 Makefile.inc bits
|
||||
5781670c0578fe89663c9085ed3ba477cf7e7913 Delete sshconnect1.c
|
||||
ea80f445e819719ccdcb237022cacfac990fdc5c Makefile.inc warning flags
|
||||
b92c93266d8234d493857bb822260dacf4366157 moduli-gen.sh tweak
|
||||
b25bf747544265b39af74fe0716dc8d9f5b63b95 Updated moduli
|
||||
1bd41cba06a7752de4df304305a8153ebfb6b0ac rsa.[ch] already removed
|
||||
e39b3902fe1d6c4a7ba6a3c58e072219f3c1e604 Makefile changes
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -74,19 +74,16 @@
|
||||
0F) If source files have been added or removed, update the appropriate
|
||||
makefiles to reflect changes in the vendor's Makefile.in.
|
||||
|
||||
10) Build libssh:
|
||||
10) Update ssh_namespace.h:
|
||||
|
||||
$ cd ../../secure/lib/libssh && make obj && make depend && make
|
||||
$ sh freebsd-namespace.sh
|
||||
|
||||
11) Follow the instructions in ssh_namespace.h to get a list of new
|
||||
symbols, and them to ssh_namespace.h. Keep it sorted!
|
||||
|
||||
12) Build and install world, reboot, test. Pay particular attention
|
||||
11) Build and install world, reboot, test. Pay particular attention
|
||||
to pam_ssh(8), which gropes inside libssh and will break if
|
||||
something significant changes or if ssh_namespace.h is out of
|
||||
whack.
|
||||
|
||||
13) Commit, and hunker down for the inevitable storm of complaints.
|
||||
12) Commit, and hunker down for the inevitable storm of complaints.
|
||||
|
||||
|
||||
|
||||
|
@ -108,7 +108,7 @@ http://www.gnu.org/software/autoconf/
|
||||
|
||||
Basic Security Module (BSM):
|
||||
|
||||
Native BSM support is know to exist in Solaris from at least 2.5.1,
|
||||
Native BSM support is known to exist in Solaris from at least 2.5.1,
|
||||
FreeBSD 6.1 and OS X. Alternatively, you may use the OpenBSM
|
||||
implementation (http://www.openbsm.org).
|
||||
|
||||
|
@ -75,27 +75,6 @@ OpenSSH contains no GPL code.
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
2)
|
||||
The 32-bit CRC compensation attack detector in deattack.c was
|
||||
contributed by CORE SDI S.A. under a BSD-style license.
|
||||
|
||||
* Cryptographic attack detector for ssh - source code
|
||||
*
|
||||
* Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
|
||||
*
|
||||
* All rights reserved. Redistribution and use in source and binary
|
||||
* forms, with or without modification, are permitted provided that
|
||||
* this copyright notice is retained.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
|
||||
* CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Ariel Futoransky <futo@core-sdi.com>
|
||||
* <http://www.core-sdi.com>
|
||||
|
||||
3)
|
||||
ssh-keyscan was contributed by David Mazieres under a BSD-style
|
||||
license.
|
||||
@ -337,4 +316,4 @@ OpenSSH contains no GPL code.
|
||||
|
||||
|
||||
------
|
||||
$OpenBSD: LICENCE,v 1.19 2004/08/30 09:18:08 markus Exp $
|
||||
$OpenBSD: LICENCE,v 1.20 2017/04/30 23:26:16 djm Exp $
|
||||
|
@ -78,10 +78,10 @@ LIBOPENSSH_OBJS=\
|
||||
LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
|
||||
authfd.o authfile.o bufaux.o bufbn.o bufec.o buffer.o \
|
||||
canohost.o channels.o cipher.o cipher-aes.o cipher-aesctr.o \
|
||||
cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
|
||||
compat.o crc32.o deattack.o fatal.o hostfile.o \
|
||||
log.o match.o md-sha256.o moduli.o nchan.o packet.o opacket.o \
|
||||
readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
|
||||
cipher-ctr.o cleanup.o \
|
||||
compat.o crc32.o fatal.o hostfile.o \
|
||||
log.o match.o moduli.o nchan.o packet.o opacket.o \
|
||||
readpass.o ttymodes.o xmalloc.o addrmatch.o \
|
||||
atomicio.o key.o dispatch.o mac.o uidswap.o uuencode.o misc.o utf8.o \
|
||||
monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
|
||||
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
|
||||
@ -92,10 +92,10 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
|
||||
kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
|
||||
kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
|
||||
kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
|
||||
platform-pledge.o platform-tracing.o
|
||||
platform-pledge.o platform-tracing.o platform-misc.o
|
||||
|
||||
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
|
||||
sshconnect.o sshconnect1.o sshconnect2.o mux.o
|
||||
sshconnect.o sshconnect2.o mux.o
|
||||
|
||||
SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
|
||||
audit.o audit-bsm.o audit-linux.o platform.o \
|
||||
@ -228,26 +228,27 @@ umac128.o: umac.c
|
||||
clean: regressclean
|
||||
rm -f *.o *.a $(TARGETS) logintest config.cache config.log
|
||||
rm -f *.out core survey
|
||||
rm -f regress/check-perm$(EXEEXT)
|
||||
rm -f regress/unittests/test_helper/*.a
|
||||
rm -f regress/unittests/test_helper/*.o
|
||||
rm -f regress/unittests/sshbuf/*.o
|
||||
rm -f regress/unittests/sshbuf/test_sshbuf
|
||||
rm -f regress/unittests/sshbuf/test_sshbuf$(EXEEXT)
|
||||
rm -f regress/unittests/sshkey/*.o
|
||||
rm -f regress/unittests/sshkey/test_sshkey
|
||||
rm -f regress/unittests/sshkey/test_sshkey$(EXEEXT)
|
||||
rm -f regress/unittests/bitmap/*.o
|
||||
rm -f regress/unittests/bitmap/test_bitmap
|
||||
rm -f regress/unittests/bitmap/test_bitmap$(EXEEXT)
|
||||
rm -f regress/unittests/conversion/*.o
|
||||
rm -f regress/unittests/conversion/test_conversion
|
||||
rm -f regress/unittests/conversion/test_conversion$(EXEEXT)
|
||||
rm -f regress/unittests/hostkeys/*.o
|
||||
rm -f regress/unittests/hostkeys/test_hostkeys
|
||||
rm -f regress/unittests/hostkeys/test_hostkeys$(EXEEXT)
|
||||
rm -f regress/unittests/kex/*.o
|
||||
rm -f regress/unittests/kex/test_kex
|
||||
rm -f regress/unittests/kex/test_kex$(EXEEXT)
|
||||
rm -f regress/unittests/match/*.o
|
||||
rm -f regress/unittests/match/test_match
|
||||
rm -f regress/unittests/match/test_match$(EXEEXT)
|
||||
rm -f regress/unittests/utf8/*.o
|
||||
rm -f regress/unittests/utf8/test_utf8
|
||||
rm -f regress/unittests/utf8/test_utf8$(EXEEXT)
|
||||
rm -f regress/misc/kexfuzz/*.o
|
||||
rm -f regress/misc/kexfuzz/kexfuzz
|
||||
rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT)
|
||||
(cd openbsd-compat && $(MAKE) clean)
|
||||
|
||||
distclean: regressclean
|
||||
|
@ -33,8 +33,8 @@ The method is documented in:
|
||||
|
||||
https://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt
|
||||
|
||||
1.3. transport: New public key algorithms "ssh-rsa-cert-v00@openssh.com",
|
||||
"ssh-dsa-cert-v00@openssh.com",
|
||||
1.3. transport: New public key algorithms "ssh-rsa-cert-v01@openssh.com",
|
||||
"ssh-dsa-cert-v01@openssh.com",
|
||||
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
|
||||
"ecdsa-sha2-nistp384-cert-v01@openssh.com" and
|
||||
"ecdsa-sha2-nistp521-cert-v01@openssh.com"
|
||||
@ -454,4 +454,4 @@ respond with a SSH_FXP_STATUS message.
|
||||
This extension is advertised in the SSH_FXP_VERSION hello with version
|
||||
"1".
|
||||
|
||||
$OpenBSD: PROTOCOL,v 1.30 2016/04/08 06:35:54 djm Exp $
|
||||
$OpenBSD: PROTOCOL,v 1.31 2017/05/26 01:40:07 djm Exp $
|
||||
|
@ -1,582 +1,5 @@
|
||||
This describes the protocol used by OpenSSH's ssh-agent.
|
||||
This file used to contain a description of the SSH agent protocol
|
||||
implemented by OpenSSH. It has since been superseded by an Internet-
|
||||
draft that is available from:
|
||||
|
||||
OpenSSH's agent supports managing keys for the standard SSH protocol
|
||||
2 as well as the legacy SSH protocol 1. Support for these key types
|
||||
is almost completely disjoint - in all but a few cases, operations on
|
||||
protocol 2 keys cannot see or affect protocol 1 keys and vice-versa.
|
||||
|
||||
Protocol 1 and protocol 2 keys are separated because of the differing
|
||||
cryptographic usage: protocol 1 private RSA keys are used to decrypt
|
||||
challenges that were encrypted with the corresponding public key,
|
||||
whereas protocol 2 RSA private keys are used to sign challenges with
|
||||
a private key for verification with the corresponding public key. It
|
||||
is considered unsound practice to use the same key for signing and
|
||||
encryption.
|
||||
|
||||
With a couple of exceptions, the protocol message names used in this
|
||||
document indicate which type of key the message relates to. SSH_*
|
||||
messages refer to protocol 1 keys only. SSH2_* messages refer to
|
||||
protocol 2 keys. Furthermore, the names also indicate whether the
|
||||
message is a request to the agent (*_AGENTC_*) or a reply from the
|
||||
agent (*_AGENT_*). Section 3 below contains the mapping of the
|
||||
protocol message names to their integer values.
|
||||
|
||||
1. Data types
|
||||
|
||||
Because of support for legacy SSH protocol 1 keys, OpenSSH's agent
|
||||
protocol makes use of some data types not defined in RFC 4251.
|
||||
|
||||
1.1 uint16
|
||||
|
||||
The "uint16" data type is a simple MSB-first 16 bit unsigned integer
|
||||
encoded in two bytes.
|
||||
|
||||
1.2 mpint1
|
||||
|
||||
The "mpint1" type represents an arbitrary precision integer (bignum).
|
||||
Its format is as follows:
|
||||
|
||||
uint16 bits
|
||||
byte[(bits + 7) / 8] bignum
|
||||
|
||||
"bignum" contains an unsigned arbitrary precision integer encoded as
|
||||
eight bits per byte in big-endian (MSB first) format.
|
||||
|
||||
Note the difference between the "mpint1" encoding and the "mpint"
|
||||
encoding defined in RFC 4251. Also note that the length of the encoded
|
||||
integer is specified in bits, not bytes and that the byte length of
|
||||
the integer must be calculated by rounding up the number of bits to the
|
||||
nearest eight.
|
||||
|
||||
2. Protocol Messages
|
||||
|
||||
All protocol messages are prefixed with their length in bytes, encoded
|
||||
as a 32 bit unsigned integer. Specifically:
|
||||
|
||||
uint32 message_length
|
||||
byte[message_length] message
|
||||
|
||||
The following message descriptions refer only to the content the
|
||||
"message" field.
|
||||
|
||||
2.1 Generic server responses
|
||||
|
||||
The following generic messages may be sent by the server in response to
|
||||
requests from the client. On success the agent may reply either with:
|
||||
|
||||
byte SSH_AGENT_SUCCESS
|
||||
|
||||
or a request-specific success message.
|
||||
|
||||
On failure, the agent may reply with:
|
||||
|
||||
byte SSH_AGENT_FAILURE
|
||||
|
||||
SSH_AGENT_FAILURE messages are also sent in reply to unknown request
|
||||
types.
|
||||
|
||||
2.2 Adding keys to the agent
|
||||
|
||||
Keys are added to the agent using the SSH_AGENTC_ADD_RSA_IDENTITY and
|
||||
SSH2_AGENTC_ADD_IDENTITY requests for protocol 1 and protocol 2 keys
|
||||
respectively.
|
||||
|
||||
Two variants of these requests are SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
|
||||
and SSH2_AGENTC_ADD_ID_CONSTRAINED - these add keys with optional
|
||||
"constraints" on their usage.
|
||||
|
||||
OpenSSH may be built with support for keys hosted on a smartcard
|
||||
or other hardware security module. These keys may be added
|
||||
to the agent using the SSH_AGENTC_ADD_SMARTCARD_KEY and
|
||||
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED requests.
|
||||
|
||||
2.2.1 Key constraints
|
||||
|
||||
The OpenSSH agent supports some basic optional constraints on key usage.
|
||||
At present there are two constraints defined.
|
||||
|
||||
The first constraint limits the validity duration of a key. It is
|
||||
encoded as:
|
||||
|
||||
byte SSH_AGENT_CONSTRAIN_LIFETIME
|
||||
uint32 seconds
|
||||
|
||||
Where "seconds" contains the number of seconds that the key shall remain
|
||||
valid measured from the moment that the agent receives it. After the
|
||||
validity period has expired, OpenSSH's agent will erase these keys from
|
||||
memory.
|
||||
|
||||
The second constraint requires the agent to seek explicit user
|
||||
confirmation before performing private key operations with the loaded
|
||||
key. This constraint is encoded as:
|
||||
|
||||
byte SSH_AGENT_CONSTRAIN_CONFIRM
|
||||
|
||||
Zero or more constraints may be specified when adding a key with one
|
||||
of the *_CONSTRAINED requests. Multiple constraints are appended
|
||||
consecutively to the end of the request:
|
||||
|
||||
byte constraint1_type
|
||||
.... constraint1_data
|
||||
byte constraint2_type
|
||||
.... constraint2_data
|
||||
....
|
||||
byte constraintN_type
|
||||
.... constraintN_data
|
||||
|
||||
Such a sequence of zero or more constraints will be referred to below
|
||||
as "constraint[]". Agents may determine whether there are constraints
|
||||
by checking whether additional data exists in the "add key" request
|
||||
after the key data itself. OpenSSH will refuse to add a key if it
|
||||
contains unknown constraints.
|
||||
|
||||
2.2.2 Add protocol 1 key
|
||||
|
||||
A client may add a protocol 1 key to an agent with the following
|
||||
request:
|
||||
|
||||
byte SSH_AGENTC_ADD_RSA_IDENTITY or
|
||||
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
|
||||
uint32 ignored
|
||||
mpint1 rsa_n
|
||||
mpint1 rsa_e
|
||||
mpint1 rsa_d
|
||||
mpint1 rsa_iqmp
|
||||
mpint1 rsa_q
|
||||
mpint1 rsa_p
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
Note that there is some redundancy in the key parameters; a key could be
|
||||
fully specified using just rsa_q, rsa_p and rsa_e at the cost of extra
|
||||
computation.
|
||||
|
||||
"key_constraints" may only be present if the request type is
|
||||
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED.
|
||||
|
||||
The agent will reply with a SSH_AGENT_SUCCESS if the key has been
|
||||
successfully added or a SSH_AGENT_FAILURE if an error occurred.
|
||||
|
||||
2.2.3 Add protocol 2 key
|
||||
|
||||
The OpenSSH agent supports DSA, ECDSA and RSA keys for protocol 2. DSA
|
||||
keys may be added using the following request
|
||||
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ssh-dss"
|
||||
mpint dsa_p
|
||||
mpint dsa_q
|
||||
mpint dsa_g
|
||||
mpint dsa_public_key
|
||||
mpint dsa_private_key
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
DSA certificates may be added with:
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ssh-dss-cert-v00@openssh.com"
|
||||
string certificate
|
||||
mpint dsa_private_key
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
ECDSA keys may be added using the following request
|
||||
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ecdsa-sha2-nistp256" |
|
||||
"ecdsa-sha2-nistp384" |
|
||||
"ecdsa-sha2-nistp521"
|
||||
string ecdsa_curve_name
|
||||
string ecdsa_public_key
|
||||
mpint ecdsa_private
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
ECDSA certificates may be added with:
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ecdsa-sha2-nistp256-cert-v01@openssh.com" |
|
||||
"ecdsa-sha2-nistp384-cert-v01@openssh.com" |
|
||||
"ecdsa-sha2-nistp521-cert-v01@openssh.com"
|
||||
string certificate
|
||||
mpint ecdsa_private_key
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
ED25519 keys may be added using the following request
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ssh-ed25519"
|
||||
string ed25519_public_key
|
||||
string ed25519_private_key || ed25519_public_key
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
ED25519 certificates may be added with:
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ssh-ed25519-cert-v01@openssh.com"
|
||||
string certificate
|
||||
string ed25519_public_key
|
||||
string ed25519_private_key || ed25519_public_key
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
For both ssh-ed25519 and ssh-ed25519-cert-v01@openssh.com keys, the private
|
||||
key has the public key appended (for historical reasons).
|
||||
|
||||
RSA keys may be added with this request:
|
||||
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ssh-rsa"
|
||||
mpint rsa_n
|
||||
mpint rsa_e
|
||||
mpint rsa_d
|
||||
mpint rsa_iqmp
|
||||
mpint rsa_p
|
||||
mpint rsa_q
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
RSA certificates may be added with this request:
|
||||
|
||||
byte SSH2_AGENTC_ADD_IDENTITY or
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED
|
||||
string "ssh-rsa-cert-v00@openssh.com"
|
||||
string certificate
|
||||
mpint rsa_d
|
||||
mpint rsa_iqmp
|
||||
mpint rsa_p
|
||||
mpint rsa_q
|
||||
string key_comment
|
||||
constraint[] key_constraints
|
||||
|
||||
Note that the 'rsa_p' and 'rsa_q' parameters are sent in the reverse
|
||||
order to the protocol 1 add keys message. As with the corresponding
|
||||
protocol 1 "add key" request, the private key is overspecified to avoid
|
||||
redundant processing.
|
||||
|
||||
For DSA, ECDSA and RSA key add requests, "key_constraints" may only be
|
||||
present if the request type is SSH2_AGENTC_ADD_ID_CONSTRAINED.
|
||||
|
||||
The agent will reply with a SSH_AGENT_SUCCESS if the key has been
|
||||
successfully added or a SSH_AGENT_FAILURE if an error occurred.
|
||||
|
||||
2.2.4 Loading keys from a smartcard
|
||||
|
||||
The OpenSSH agent may have optional smartcard support built in to it. If
|
||||
so, it supports an operation to load keys from a smartcard. Technically,
|
||||
only the public components of the keys are loaded into the agent so
|
||||
this operation really arranges for future private key operations to be
|
||||
delegated to the smartcard.
|
||||
|
||||
byte SSH_AGENTC_ADD_SMARTCARD_KEY or
|
||||
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED
|
||||
string reader_id
|
||||
string pin
|
||||
constraint[] key_constraints
|
||||
|
||||
"reader_id" is an identifier to a smartcard reader and "pin"
|
||||
is a PIN or passphrase used to unlock the private key(s) on the
|
||||
device. "key_constraints" may only be present if the request type is
|
||||
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED.
|
||||
|
||||
This operation may load all SSH keys that are unlocked using the
|
||||
"pin" on the specified reader. The type of key loaded (protocol 1
|
||||
or protocol 2) will be specified by the smartcard itself, it is not
|
||||
client-specified.
|
||||
|
||||
The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
|
||||
been successfully loaded or a SSH_AGENT_FAILURE if an error occurred.
|
||||
The agent will also return SSH_AGENT_FAILURE if it does not support
|
||||
smartcards.
|
||||
|
||||
2.3 Removing multiple keys
|
||||
|
||||
A client may request that an agent delete all protocol 1 keys using the
|
||||
following request:
|
||||
|
||||
byte SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES
|
||||
|
||||
This message requests the deletion of all protocol 2 keys:
|
||||
|
||||
byte SSH2_AGENTC_REMOVE_ALL_IDENTITIES
|
||||
|
||||
On success, the agent will delete all keys of the requested type and
|
||||
reply with a SSH_AGENT_SUCCESS message. If an error occurred, the agent
|
||||
will reply with SSH_AGENT_FAILURE.
|
||||
|
||||
Note that, to delete all keys (both protocol 1 and 2), a client
|
||||
must send both a SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES and a
|
||||
SSH2_AGENTC_REMOVE_ALL_IDENTITIES request.
|
||||
|
||||
2.4 Removing specific keys
|
||||
|
||||
2.4.1 Removing a protocol 1 key
|
||||
|
||||
Removal of a protocol 1 key may be requested with the following message:
|
||||
|
||||
byte SSH_AGENTC_REMOVE_RSA_IDENTITY
|
||||
uint32 key_bits
|
||||
mpint1 rsa_e
|
||||
mpint1 rsa_n
|
||||
|
||||
Note that key_bits is strictly redundant, as it may be inferred by the
|
||||
length of rsa_n.
|
||||
|
||||
The agent will delete any private key matching the specified public key
|
||||
and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
|
||||
return SSH_AGENT_FAILURE.
|
||||
|
||||
2.4.2 Removing a protocol 2 key
|
||||
|
||||
Protocol 2 keys may be removed with the following request:
|
||||
|
||||
byte SSH2_AGENTC_REMOVE_IDENTITY
|
||||
string key_blob
|
||||
|
||||
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
|
||||
Algorithms" for any of the supported protocol 2 key types.
|
||||
|
||||
The agent will delete any private key matching the specified public key
|
||||
and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
|
||||
return SSH_AGENT_FAILURE.
|
||||
|
||||
2.4.3 Removing keys loaded from a smartcard
|
||||
|
||||
A client may request that a server remove one or more smartcard-hosted
|
||||
keys using this message:
|
||||
|
||||
byte SSH_AGENTC_REMOVE_SMARTCARD_KEY
|
||||
string reader_id
|
||||
string pin
|
||||
|
||||
"reader_id" the an identifier to a smartcard reader and "pin" is a PIN
|
||||
or passphrase used to unlock the private key(s) on the device.
|
||||
|
||||
When this message is received, and if the agent supports
|
||||
smartcard-hosted keys, it will delete all keys that are hosted on the
|
||||
specified smartcard that may be accessed with the given "pin".
|
||||
|
||||
The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
|
||||
been successfully removed or a SSH_AGENT_FAILURE if an error occurred.
|
||||
The agent will also return SSH_AGENT_FAILURE if it does not support
|
||||
smartcards.
|
||||
|
||||
2.5 Requesting a list of known keys
|
||||
|
||||
An agent may be requested to list which keys it holds. Different
|
||||
requests exist for protocol 1 and protocol 2 keys.
|
||||
|
||||
2.5.1 Requesting a list of protocol 1 keys
|
||||
|
||||
To request a list of protocol 1 keys that are held in the agent, a
|
||||
client may send the following message:
|
||||
|
||||
byte SSH_AGENTC_REQUEST_RSA_IDENTITIES
|
||||
|
||||
The agent will reply with the following message:
|
||||
|
||||
byte SSH_AGENT_RSA_IDENTITIES_ANSWER
|
||||
uint32 num_keys
|
||||
|
||||
Followed by zero or more consecutive keys, encoded as:
|
||||
|
||||
uint32 bits
|
||||
mpint1 rsa_e
|
||||
mpint1 rsa_n
|
||||
string key_comment
|
||||
|
||||
2.5.2 Requesting a list of protocol 2 keys
|
||||
|
||||
A client may send the following message to request a list of
|
||||
protocol 2 keys that are stored in the agent:
|
||||
|
||||
byte SSH2_AGENTC_REQUEST_IDENTITIES
|
||||
|
||||
The agent will reply with the following message header:
|
||||
|
||||
byte SSH2_AGENT_IDENTITIES_ANSWER
|
||||
uint32 num_keys
|
||||
|
||||
Followed by zero or more consecutive keys, encoded as:
|
||||
|
||||
string key_blob
|
||||
string key_comment
|
||||
|
||||
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
|
||||
Algorithms" for any of the supported protocol 2 key types.
|
||||
|
||||
2.6 Private key operations
|
||||
|
||||
The purpose of the agent is to perform private key operations, such as
|
||||
signing and encryption without requiring a passphrase to unlock the
|
||||
key and without allowing the private key itself to be exposed. There
|
||||
are separate requests for the protocol 1 and protocol 2 private key
|
||||
operations.
|
||||
|
||||
2.6.1 Protocol 1 private key challenge
|
||||
|
||||
The private key operation used in version 1 of the SSH protocol is
|
||||
decrypting a challenge that has been encrypted with a public key.
|
||||
It may be requested using this message:
|
||||
|
||||
byte SSH_AGENTC_RSA_CHALLENGE
|
||||
uint32 ignored
|
||||
mpint1 rsa_e
|
||||
mpint1 rsa_n
|
||||
mpint1 encrypted_challenge
|
||||
byte[16] session_id
|
||||
uint32 response_type /* must be 1 */
|
||||
|
||||
"rsa_e" and "rsa_n" are used to identify which private key to use.
|
||||
"encrypted_challenge" is a challenge blob that has (presumably)
|
||||
been encrypted with the public key and must be in the range
|
||||
1 <= encrypted_challenge < 2^256. "session_id" is the SSH protocol 1
|
||||
session ID (computed from the server host key, the server semi-ephemeral
|
||||
key and the session cookie).
|
||||
|
||||
"ignored" and "response_type" exist for compatibility with legacy
|
||||
implementations. "response_type" must be equal to 1; other response
|
||||
types are not supported.
|
||||
|
||||
On receiving this request, the server decrypts the "encrypted_challenge"
|
||||
using the private key matching the supplied (rsa_e, rsa_n) values. For
|
||||
the response derivation, the decrypted challenge is represented as an
|
||||
unsigned, big-endian integer encoded in a 32 byte buffer (i.e. values
|
||||
smaller than 2^248 will have leading 0 bytes).
|
||||
|
||||
The response value is then calculated as:
|
||||
|
||||
response = MD5(decrypted_challenge || session_id)
|
||||
|
||||
and returned in the following message
|
||||
|
||||
byte SSH_AGENT_RSA_RESPONSE
|
||||
byte[16] response
|
||||
|
||||
If the agent cannot find the key specified by the supplied (rsa_e,
|
||||
rsa_n) then it will return SSH_AGENT_FAILURE.
|
||||
|
||||
2.6.2 Protocol 2 private key signature request
|
||||
|
||||
A client may use the following message to request signing of data using
|
||||
a protocol 2 key:
|
||||
|
||||
byte SSH2_AGENTC_SIGN_REQUEST
|
||||
string key_blob
|
||||
string data
|
||||
uint32 flags
|
||||
|
||||
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
|
||||
Algorithms" for any of the supported protocol 2 key types. "flags" is
|
||||
a bit-mask, but at present only one possible value is defined (see below
|
||||
for its meaning):
|
||||
|
||||
SSH_AGENT_OLD_SIGNATURE 1
|
||||
|
||||
Upon receiving this request, the agent will look up the private key that
|
||||
corresponds to the public key contained in key_blob. It will use this
|
||||
private key to sign the "data" and produce a signature blob using the
|
||||
key type-specific method described in RFC 4253 section 6.6 "Public Key
|
||||
Algorithms".
|
||||
|
||||
An exception to this is for "ssh-dss" keys where the "flags" word
|
||||
contains the value SSH_AGENT_OLD_SIGNATURE. In this case, a legacy
|
||||
signature encoding is used in lieu of the standard one. In this case,
|
||||
the DSA signature blob is encoded as:
|
||||
|
||||
byte[40] signature
|
||||
|
||||
The signature will be returned in the response message:
|
||||
|
||||
byte SSH2_AGENT_SIGN_RESPONSE
|
||||
string signature_blob
|
||||
|
||||
If the agent cannot find the key specified by the supplied key_blob then
|
||||
it will return SSH_AGENT_FAILURE.
|
||||
|
||||
2.7 Locking or unlocking an agent
|
||||
|
||||
The agent supports temporary locking with a passphrase to suspend
|
||||
processing of sensitive operations until it has been unlocked with the
|
||||
same passphrase. To lock an agent, a client send the following request:
|
||||
|
||||
byte SSH_AGENTC_LOCK
|
||||
string passphrase
|
||||
|
||||
Upon receipt of this message and if the agent is not already locked,
|
||||
it will suspend processing requests and return a SSH_AGENT_SUCCESS
|
||||
reply. If the agent is already locked, it will return SSH_AGENT_FAILURE.
|
||||
|
||||
While locked, the agent will refuse all requests except
|
||||
SSH_AGENTC_UNLOCK, SSH_AGENTC_REQUEST_RSA_IDENTITIES and
|
||||
SSH2_AGENTC_REQUEST_IDENTITIES. The "request identities" requests are
|
||||
treated specially by a locked agent: it will always return an empty list
|
||||
of keys.
|
||||
|
||||
To unlock an agent, a client may request:
|
||||
|
||||
byte SSH_AGENTC_UNLOCK
|
||||
string passphrase
|
||||
|
||||
If the passphrase matches and the agent is locked, then it will resume
|
||||
processing all requests and return SSH_AGENT_SUCCESS. If the agent
|
||||
is not locked or the passphrase does not match then it will return
|
||||
SSH_AGENT_FAILURE.
|
||||
|
||||
Locking and unlocking affects both protocol 1 and protocol 2 keys.
|
||||
|
||||
3. Protocol message numbers
|
||||
|
||||
3.1 Requests from client to agent for protocol 1 key operations
|
||||
|
||||
SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
||||
SSH_AGENTC_RSA_CHALLENGE 3
|
||||
SSH_AGENTC_ADD_RSA_IDENTITY 7
|
||||
SSH_AGENTC_REMOVE_RSA_IDENTITY 8
|
||||
SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
|
||||
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
|
||||
|
||||
3.2 Requests from client to agent for protocol 2 key operations
|
||||
|
||||
SSH2_AGENTC_REQUEST_IDENTITIES 11
|
||||
SSH2_AGENTC_SIGN_REQUEST 13
|
||||
SSH2_AGENTC_ADD_IDENTITY 17
|
||||
SSH2_AGENTC_REMOVE_IDENTITY 18
|
||||
SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
|
||||
SSH2_AGENTC_ADD_ID_CONSTRAINED 25
|
||||
|
||||
3.3 Key-type independent requests from client to agent
|
||||
|
||||
SSH_AGENTC_ADD_SMARTCARD_KEY 20
|
||||
SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
|
||||
SSH_AGENTC_LOCK 22
|
||||
SSH_AGENTC_UNLOCK 23
|
||||
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
|
||||
|
||||
3.4 Generic replies from agent to client
|
||||
|
||||
SSH_AGENT_FAILURE 5
|
||||
SSH_AGENT_SUCCESS 6
|
||||
|
||||
3.5 Replies from agent to client for protocol 1 key operations
|
||||
|
||||
SSH_AGENT_RSA_IDENTITIES_ANSWER 2
|
||||
SSH_AGENT_RSA_RESPONSE 4
|
||||
|
||||
3.6 Replies from agent to client for protocol 2 key operations
|
||||
|
||||
SSH2_AGENT_IDENTITIES_ANSWER 12
|
||||
SSH2_AGENT_SIGN_RESPONSE 14
|
||||
|
||||
3.7 Key constraint identifiers
|
||||
|
||||
SSH_AGENT_CONSTRAIN_LIFETIME 1
|
||||
SSH_AGENT_CONSTRAIN_CONFIRM 2
|
||||
|
||||
$OpenBSD: PROTOCOL.agent,v 1.11 2016/05/19 07:45:32 djm Exp $
|
||||
https://tools.ietf.org/html/draft-miller-ssh-agent-02
|
||||
|
@ -192,12 +192,13 @@ compatibility.
|
||||
The reserved field is currently unused and is ignored in this version of
|
||||
the protocol.
|
||||
|
||||
signature key contains the CA key used to sign the certificate.
|
||||
The valid key types for CA keys are ssh-rsa, ssh-dss and the ECDSA types
|
||||
ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained"
|
||||
certificates, where the signature key type is a certificate type itself
|
||||
are NOT supported. Note that it is possible for a RSA certificate key to
|
||||
be signed by a DSS or ECDSA CA key and vice-versa.
|
||||
The signature key field contains the CA key used to sign the
|
||||
certificate. The valid key types for CA keys are ssh-rsa,
|
||||
ssh-dss, ssh-ed25519 and the ECDSA types ecdsa-sha2-nistp256,
|
||||
ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained" certificates, where
|
||||
the signature key type is a certificate type itself are NOT supported.
|
||||
Note that it is possible for a RSA certificate key to be signed by a
|
||||
Ed25519 or ECDSA CA key and vice-versa.
|
||||
|
||||
signature is computed over all preceding fields from the initial string
|
||||
up to, and including the signature key. Signatures are computed and
|
||||
@ -223,6 +224,9 @@ option-specific information (see below). All options are
|
||||
"critical", if an implementation does not recognise a option
|
||||
then the validating party should refuse to accept the certificate.
|
||||
|
||||
Custom options should append the originating author or organisation's
|
||||
domain name to the option name, e.g. "my-option@example.com".
|
||||
|
||||
No critical options are defined for host certificates at present. The
|
||||
supported user certificate options and the contents and structure of
|
||||
their data fields are:
|
||||
@ -254,6 +258,9 @@ as is the requirement that each name appear only once.
|
||||
If an implementation does not recognise an extension, then it should
|
||||
ignore it.
|
||||
|
||||
Custom options should append the originating author or organisation's
|
||||
domain name to the option name, e.g. "my-option@example.com".
|
||||
|
||||
No extensions are defined for host certificates at present. The
|
||||
supported user certificate extensions and the contents and structure of
|
||||
their data fields are:
|
||||
@ -284,4 +291,4 @@ permit-user-rc empty Flag indicating that execution of
|
||||
of this script will not be permitted if
|
||||
this option is not present.
|
||||
|
||||
$OpenBSD: PROTOCOL.certkeys,v 1.10 2016/05/03 10:27:59 djm Exp $
|
||||
$OpenBSD: PROTOCOL.certkeys,v 1.12 2017/05/31 04:29:44 djm Exp $
|
||||
|
@ -1,4 +1,4 @@
|
||||
See https://www.openssh.com/releasenotes.html#7.5p1 for the release notes.
|
||||
See https://www.openssh.com/releasenotes.html#7.6p1 for the release notes.
|
||||
|
||||
Please read https://www.openssh.com/report.html for bug reporting
|
||||
instructions and note that we do not use Github for bug reporting or
|
||||
@ -30,7 +30,8 @@ The PAM support is now more functional than the popular packages of
|
||||
commercial ssh-1.2.x. It checks "account" and "session" modules for
|
||||
all logins, not just when using password authentication.
|
||||
|
||||
OpenSSH depends on Zlib[3], OpenSSL[4] and optionally PAM[5].
|
||||
OpenSSH depends on Zlib[3], OpenSSL[4], and optionally PAM[5] and
|
||||
libedit[6]
|
||||
|
||||
There is now several mailing lists for this port of OpenSSH. Please
|
||||
refer to https://www.openssh.com/list.html for details on how to join.
|
||||
@ -38,7 +39,7 @@ refer to https://www.openssh.com/list.html for details on how to join.
|
||||
Please send bug reports and patches to the mailing list
|
||||
openssh-unix-dev@mindrot.org. The list is open to posting by unsubscribed
|
||||
users. Code contribution are welcomed, but please follow the OpenBSD
|
||||
style guidelines[6].
|
||||
style guidelines[7].
|
||||
|
||||
Please refer to the INSTALL document for information on how to install
|
||||
OpenSSH on your system.
|
||||
@ -61,4 +62,5 @@ References -
|
||||
[5] http://www.openpam.org
|
||||
http://www.kernel.org/pub/linux/libs/pam/
|
||||
(PAM also is standard on Solaris and HP-UX 11)
|
||||
[6] http://man.openbsd.org/style.9
|
||||
[6] http://thrysoee.dk/editline/ (portable version)
|
||||
[7] http://man.openbsd.org/style.9
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-options.c,v 1.72 2016/11/30 02:57:40 djm Exp $ */
|
||||
/* $OpenBSD: auth-options.c,v 1.74 2017/09/12 06:32:07 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -61,9 +61,13 @@ char *authorized_principals = NULL;
|
||||
|
||||
extern ServerOptions options;
|
||||
|
||||
/* XXX refactor to be stateless */
|
||||
|
||||
void
|
||||
auth_clear_options(void)
|
||||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
|
||||
no_agent_forwarding_flag = 0;
|
||||
no_port_forwarding_flag = 0;
|
||||
no_pty_flag = 0;
|
||||
@ -81,7 +85,7 @@ auth_clear_options(void)
|
||||
free(authorized_principals);
|
||||
authorized_principals = NULL;
|
||||
forced_tun_device = -1;
|
||||
channel_clear_permitted_opens();
|
||||
channel_clear_permitted_opens(ssh);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -117,9 +121,11 @@ match_flag(const char *opt, int allow_negate, char **optsp, const char *msg)
|
||||
/*
|
||||
* return 1 if access is granted, 0 if not.
|
||||
* side effect: sets key option flags
|
||||
* XXX remove side effects; fill structure instead.
|
||||
*/
|
||||
int
|
||||
auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
|
||||
auth_parse_options(struct passwd *pw, char *opts, const char *file,
|
||||
u_long linenum)
|
||||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
const char *cp;
|
||||
@ -379,7 +385,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
|
||||
goto bad_option;
|
||||
}
|
||||
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0)
|
||||
channel_add_permitted_opens(host, port);
|
||||
channel_add_permitted_opens(ssh, host, port);
|
||||
free(patterns);
|
||||
goto next_option;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-options.h,v 1.22 2016/11/30 02:57:40 djm Exp $ */
|
||||
/* $OpenBSD: auth-options.h,v 1.23 2017/05/31 10:54:00 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -33,7 +33,7 @@ extern int forced_tun_device;
|
||||
extern int key_is_cert_authority;
|
||||
extern char *authorized_principals;
|
||||
|
||||
int auth_parse_options(struct passwd *, char *, char *, u_long);
|
||||
int auth_parse_options(struct passwd *, char *, const char *, u_long);
|
||||
void auth_clear_options(void);
|
||||
int auth_cert_options(struct sshkey *, struct passwd *, const char **);
|
||||
|
||||
|
@ -107,7 +107,6 @@ extern char *__progname;
|
||||
|
||||
extern ServerOptions options;
|
||||
extern Buffer loginmsg;
|
||||
extern int compat20;
|
||||
extern u_int utmp_len;
|
||||
|
||||
/* so we don't silently change behaviour */
|
||||
@ -469,7 +468,6 @@ sshpam_thread(void *ctxtp)
|
||||
if (sshpam_err != PAM_SUCCESS)
|
||||
goto auth_fail;
|
||||
|
||||
if (compat20) {
|
||||
if (!do_pam_account()) {
|
||||
sshpam_err = PAM_ACCT_EXPIRED;
|
||||
goto auth_fail;
|
||||
@ -481,7 +479,6 @@ sshpam_thread(void *ctxtp)
|
||||
goto auth_fail;
|
||||
sshpam_password_change_required(0);
|
||||
}
|
||||
}
|
||||
|
||||
buffer_put_cstring(&buffer, "OK");
|
||||
|
||||
@ -932,6 +929,27 @@ finish_pam(void)
|
||||
sshpam_cleanup();
|
||||
}
|
||||
|
||||
static void
|
||||
expose_authinfo(const char *caller)
|
||||
{
|
||||
char *auth_info;
|
||||
|
||||
/*
|
||||
* Expose authentication information to PAM.
|
||||
* The enviornment variable is versioned. Please increment the
|
||||
* version suffix if the format of session_info changes.
|
||||
*/
|
||||
if (sshpam_authctxt->session_info == NULL)
|
||||
auth_info = xstrdup("");
|
||||
else if ((auth_info = sshbuf_dup_string(
|
||||
sshpam_authctxt->session_info)) == NULL)
|
||||
fatal("%s: sshbuf_dup_string failed", __func__);
|
||||
|
||||
debug2("%s: auth information in SSH_AUTH_INFO_0", caller);
|
||||
do_pam_putenv("SSH_AUTH_INFO_0", auth_info);
|
||||
free(auth_info);
|
||||
}
|
||||
|
||||
u_int
|
||||
do_pam_account(void)
|
||||
{
|
||||
@ -939,6 +957,8 @@ do_pam_account(void)
|
||||
if (sshpam_account_status != -1)
|
||||
return (sshpam_account_status);
|
||||
|
||||
expose_authinfo(__func__);
|
||||
|
||||
sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
|
||||
debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
|
||||
pam_strerror(sshpam_handle, sshpam_err));
|
||||
@ -1063,6 +1083,9 @@ void
|
||||
do_pam_session(void)
|
||||
{
|
||||
debug3("PAM: opening session");
|
||||
|
||||
expose_authinfo(__func__);
|
||||
|
||||
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
|
||||
(const void *)&store_conv);
|
||||
if (sshpam_err != PAM_SUCCESS)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth.c,v 1.119 2016/12/15 21:29:05 dtucker Exp $ */
|
||||
/* $OpenBSD: auth.c,v 1.124 2017/09/12 06:32:07 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -44,9 +44,6 @@ __RCSID("$FreeBSD$");
|
||||
#ifdef USE_SHADOW
|
||||
#include <shadow.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIBGEN_H
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -269,21 +266,41 @@ allowed_user(struct passwd * pw)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
auth_info(Authctxt *authctxt, const char *fmt, ...)
|
||||
/*
|
||||
* Formats any key left in authctxt->auth_method_key for inclusion in
|
||||
* auth_log()'s message. Also includes authxtct->auth_method_info if present.
|
||||
*/
|
||||
static char *
|
||||
format_method_key(Authctxt *authctxt)
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
const struct sshkey *key = authctxt->auth_method_key;
|
||||
const char *methinfo = authctxt->auth_method_info;
|
||||
char *fp, *ret = NULL;
|
||||
|
||||
free(authctxt->info);
|
||||
authctxt->info = NULL;
|
||||
if (key == NULL)
|
||||
return NULL;
|
||||
|
||||
va_start(ap, fmt);
|
||||
i = vasprintf(&authctxt->info, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (i < 0 || authctxt->info == NULL)
|
||||
fatal("vasprintf failed");
|
||||
if (key_is_cert(key)) {
|
||||
fp = sshkey_fingerprint(key->cert->signature_key,
|
||||
options.fingerprint_hash, SSH_FP_DEFAULT);
|
||||
xasprintf(&ret, "%s ID %s (serial %llu) CA %s %s%s%s",
|
||||
sshkey_type(key), key->cert->key_id,
|
||||
(unsigned long long)key->cert->serial,
|
||||
sshkey_type(key->cert->signature_key),
|
||||
fp == NULL ? "(null)" : fp,
|
||||
methinfo == NULL ? "" : ", ",
|
||||
methinfo == NULL ? "" : methinfo);
|
||||
free(fp);
|
||||
} else {
|
||||
fp = sshkey_fingerprint(key, options.fingerprint_hash,
|
||||
SSH_FP_DEFAULT);
|
||||
xasprintf(&ret, "%s %s%s%s", sshkey_type(key),
|
||||
fp == NULL ? "(null)" : fp,
|
||||
methinfo == NULL ? "" : ", ",
|
||||
methinfo == NULL ? "" : methinfo);
|
||||
free(fp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
@ -292,7 +309,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
|
||||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
void (*authlog) (const char *fmt,...) = verbose;
|
||||
char *authmsg;
|
||||
const char *authmsg;
|
||||
char *extra = NULL;
|
||||
|
||||
if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
|
||||
return;
|
||||
@ -314,6 +332,11 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
|
||||
BLACKLIST_NOTIFY(BLACKLIST_AUTH_OK, "ssh");
|
||||
}
|
||||
|
||||
if ((extra = format_method_key(authctxt)) == NULL) {
|
||||
if (authctxt->auth_method_info != NULL)
|
||||
extra = xstrdup(authctxt->auth_method_info);
|
||||
}
|
||||
|
||||
authlog("%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s",
|
||||
authmsg,
|
||||
method,
|
||||
@ -322,10 +345,10 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
|
||||
authctxt->user,
|
||||
ssh_remote_ipaddr(ssh),
|
||||
ssh_remote_port(ssh),
|
||||
authctxt->info != NULL ? ": " : "",
|
||||
authctxt->info != NULL ? authctxt->info : "");
|
||||
free(authctxt->info);
|
||||
authctxt->info = NULL;
|
||||
extra != NULL ? ": " : "",
|
||||
extra != NULL ? extra : "");
|
||||
|
||||
free(extra);
|
||||
|
||||
#ifdef CUSTOM_FAILED_LOGIN
|
||||
if (authenticated == 0 && !authctxt->postponed &&
|
||||
@ -433,7 +456,7 @@ authorized_principals_file(struct passwd *pw)
|
||||
|
||||
/* return ok if key exists in sysfile or userfile */
|
||||
HostStatus
|
||||
check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
|
||||
check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
|
||||
const char *sysfile, const char *userfile)
|
||||
{
|
||||
char *user_hostfile;
|
||||
@ -477,98 +500,6 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
|
||||
return host_status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a given path for security. This is defined as all components
|
||||
* of the path to the file must be owned by either the owner of
|
||||
* of the file or root and no directories must be group or world writable.
|
||||
*
|
||||
* XXX Should any specific check be done for sym links ?
|
||||
*
|
||||
* Takes a file name, its stat information (preferably from fstat() to
|
||||
* avoid races), the uid of the expected owner, their home directory and an
|
||||
* error buffer plus max size as arguments.
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
int
|
||||
auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
|
||||
uid_t uid, char *err, size_t errlen)
|
||||
{
|
||||
char buf[PATH_MAX], homedir[PATH_MAX];
|
||||
char *cp;
|
||||
int comparehome = 0;
|
||||
struct stat st;
|
||||
|
||||
if (realpath(name, buf) == NULL) {
|
||||
snprintf(err, errlen, "realpath %s failed: %s", name,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
|
||||
comparehome = 1;
|
||||
|
||||
if (!S_ISREG(stp->st_mode)) {
|
||||
snprintf(err, errlen, "%s is not a regular file", buf);
|
||||
return -1;
|
||||
}
|
||||
if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
|
||||
(stp->st_mode & 022) != 0) {
|
||||
snprintf(err, errlen, "bad ownership or modes for file %s",
|
||||
buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* for each component of the canonical path, walking upwards */
|
||||
for (;;) {
|
||||
if ((cp = dirname(buf)) == NULL) {
|
||||
snprintf(err, errlen, "dirname() failed");
|
||||
return -1;
|
||||
}
|
||||
strlcpy(buf, cp, sizeof(buf));
|
||||
|
||||
if (stat(buf, &st) < 0 ||
|
||||
(!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
|
||||
(st.st_mode & 022) != 0) {
|
||||
snprintf(err, errlen,
|
||||
"bad ownership or modes for directory %s", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If are past the homedir then we can stop */
|
||||
if (comparehome && strcmp(homedir, buf) == 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* dirname should always complete with a "/" path,
|
||||
* but we can be paranoid and check for "." too
|
||||
*/
|
||||
if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Version of secure_path() that accepts an open file descriptor to
|
||||
* avoid races.
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
static int
|
||||
secure_filename(FILE *f, const char *file, struct passwd *pw,
|
||||
char *err, size_t errlen)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
/* check the open file to avoid races */
|
||||
if (fstat(fileno(f), &st) < 0) {
|
||||
snprintf(err, errlen, "cannot stat file %s: %s",
|
||||
file, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
|
||||
}
|
||||
|
||||
static FILE *
|
||||
auth_openfile(const char *file, struct passwd *pw, int strict_modes,
|
||||
int log_missing, char *file_type)
|
||||
@ -601,7 +532,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
|
||||
return NULL;
|
||||
}
|
||||
if (strict_modes &&
|
||||
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
|
||||
safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) {
|
||||
fclose(f);
|
||||
logit("Authentication refused: %s", line);
|
||||
auth_debug_add("Ignored %s: %s", file_type, line);
|
||||
@ -640,6 +571,8 @@ getpwnamallow(const char *user)
|
||||
|
||||
ci->user = user;
|
||||
parse_server_match_config(&options, ci);
|
||||
log_change_level(options.log_level);
|
||||
process_permitopen(ssh, &options);
|
||||
|
||||
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
|
||||
aix_setauthdb(user);
|
||||
@ -700,7 +633,7 @@ getpwnamallow(const char *user)
|
||||
|
||||
/* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
|
||||
int
|
||||
auth_key_is_revoked(Key *key)
|
||||
auth_key_is_revoked(struct sshkey *key)
|
||||
{
|
||||
char *fp = NULL;
|
||||
int r;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth.h,v 1.89 2016/08/13 17:47:41 markus Exp $ */
|
||||
/* $OpenBSD: auth.h,v 1.93 2017/08/18 05:36:45 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
@ -44,6 +44,7 @@
|
||||
|
||||
struct ssh;
|
||||
struct sshkey;
|
||||
struct sshbuf;
|
||||
|
||||
typedef struct Authctxt Authctxt;
|
||||
typedef struct Authmethod Authmethod;
|
||||
@ -62,13 +63,17 @@ struct Authctxt {
|
||||
char *service;
|
||||
struct passwd *pw; /* set if 'valid' */
|
||||
char *style;
|
||||
|
||||
/* Method lists for multiple authentication */
|
||||
char **auth_methods; /* modified from server config */
|
||||
u_int num_auth_methods;
|
||||
|
||||
/* Authentication method-specific data */
|
||||
void *methoddata;
|
||||
void *kbdintctxt;
|
||||
char *info; /* Extra info for next auth_log */
|
||||
#ifdef BSD_AUTH
|
||||
auth_session_t *as;
|
||||
#endif
|
||||
char **auth_methods; /* modified from server config */
|
||||
u_int num_auth_methods;
|
||||
#ifdef KRB5
|
||||
krb5_context krb5_ctx;
|
||||
krb5_ccache krb5_fwd_ccache;
|
||||
@ -76,12 +81,20 @@ struct Authctxt {
|
||||
char *krb5_ticket_file;
|
||||
char *krb5_ccname;
|
||||
#endif
|
||||
Buffer *loginmsg;
|
||||
void *methoddata;
|
||||
struct sshbuf *loginmsg;
|
||||
|
||||
struct sshkey **prev_userkeys;
|
||||
u_int nprev_userkeys;
|
||||
/* Authentication keys already used; these will be refused henceforth */
|
||||
struct sshkey **prev_keys;
|
||||
u_int nprev_keys;
|
||||
|
||||
/* Last used key and ancilliary information from active auth method */
|
||||
struct sshkey *auth_method_key;
|
||||
char *auth_method_info;
|
||||
|
||||
/* Information exposed to session */
|
||||
struct sshbuf *session_info; /* Auth info for environment */
|
||||
};
|
||||
|
||||
/*
|
||||
* Every authentication method has to handle authentication requests for
|
||||
* non-existing users, or for users that are not allowed to login. In this
|
||||
@ -91,7 +104,7 @@ struct Authctxt {
|
||||
|
||||
struct Authmethod {
|
||||
char *name;
|
||||
int (*userauth)(Authctxt *authctxt);
|
||||
int (*userauth)(struct ssh *);
|
||||
int *enabled;
|
||||
};
|
||||
|
||||
@ -117,16 +130,21 @@ auth_rhosts2(struct passwd *, const char *, const char *, const char *);
|
||||
|
||||
int auth_password(Authctxt *, const char *);
|
||||
|
||||
int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
|
||||
int user_key_allowed(struct passwd *, Key *, int);
|
||||
void pubkey_auth_info(Authctxt *, const Key *, const char *, ...)
|
||||
__attribute__((__format__ (printf, 3, 4)));
|
||||
void auth2_record_userkey(Authctxt *, struct sshkey *);
|
||||
int auth2_userkey_already_used(Authctxt *, struct sshkey *);
|
||||
int hostbased_key_allowed(struct passwd *, const char *, char *,
|
||||
struct sshkey *);
|
||||
int user_key_allowed(struct passwd *, struct sshkey *, int);
|
||||
int auth2_key_already_used(Authctxt *, const struct sshkey *);
|
||||
|
||||
struct stat;
|
||||
int auth_secure_path(const char *, struct stat *, const char *, uid_t,
|
||||
char *, size_t);
|
||||
/*
|
||||
* Handling auth method-specific information for logging and prevention
|
||||
* of key reuse during multiple authentication.
|
||||
*/
|
||||
void auth2_authctxt_reset_info(Authctxt *);
|
||||
void auth2_record_key(Authctxt *, int, const struct sshkey *);
|
||||
void auth2_record_info(Authctxt *authctxt, const char *, ...)
|
||||
__attribute__((__format__ (printf, 2, 3)))
|
||||
__attribute__((__nonnull__ (2)));
|
||||
void auth2_update_session_info(Authctxt *, const char *, const char *);
|
||||
|
||||
#ifdef KRB5
|
||||
int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
|
||||
@ -149,12 +167,9 @@ void disable_forwarding(void);
|
||||
|
||||
void do_authentication2(Authctxt *);
|
||||
|
||||
void auth_info(Authctxt *authctxt, const char *, ...)
|
||||
__attribute__((__format__ (printf, 2, 3)))
|
||||
__attribute__((__nonnull__ (2)));
|
||||
void auth_log(Authctxt *, int, int, const char *, const char *);
|
||||
void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
|
||||
void userauth_finish(Authctxt *, int, const char *, const char *);
|
||||
void userauth_finish(struct ssh *, int, const char *, const char *);
|
||||
int auth_root_allowed(const char *);
|
||||
|
||||
void userauth_send_banner(const char *);
|
||||
@ -167,8 +182,8 @@ int auth2_method_allowed(Authctxt *, const char *, const char *);
|
||||
|
||||
void privsep_challenge_enable(void);
|
||||
|
||||
int auth2_challenge(Authctxt *, char *);
|
||||
void auth2_challenge_stop(Authctxt *);
|
||||
int auth2_challenge(struct ssh *, char *);
|
||||
void auth2_challenge_stop(struct ssh *);
|
||||
int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
|
||||
int bsdauth_respond(void *, u_int, char **);
|
||||
int skey_query(void *, char **, char **, u_int *, char ***, u_int **);
|
||||
@ -182,22 +197,22 @@ char *authorized_principals_file(struct passwd *);
|
||||
|
||||
FILE *auth_openkeyfile(const char *, struct passwd *, int);
|
||||
FILE *auth_openprincipals(const char *, struct passwd *, int);
|
||||
int auth_key_is_revoked(Key *);
|
||||
int auth_key_is_revoked(struct sshkey *);
|
||||
|
||||
const char *auth_get_canonical_hostname(struct ssh *, int);
|
||||
|
||||
HostStatus
|
||||
check_key_in_hostfiles(struct passwd *, Key *, const char *,
|
||||
check_key_in_hostfiles(struct passwd *, struct sshkey *, const char *,
|
||||
const char *, const char *);
|
||||
|
||||
/* hostkey handling */
|
||||
Key *get_hostkey_by_index(int);
|
||||
Key *get_hostkey_public_by_index(int, struct ssh *);
|
||||
Key *get_hostkey_public_by_type(int, int, struct ssh *);
|
||||
Key *get_hostkey_private_by_type(int, int, struct ssh *);
|
||||
int get_hostkey_index(Key *, int, struct ssh *);
|
||||
int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *,
|
||||
const u_char *, size_t, const char *, u_int);
|
||||
struct sshkey *get_hostkey_by_index(int);
|
||||
struct sshkey *get_hostkey_public_by_index(int, struct ssh *);
|
||||
struct sshkey *get_hostkey_public_by_type(int, int, struct ssh *);
|
||||
struct sshkey *get_hostkey_private_by_type(int, int, struct ssh *);
|
||||
int get_hostkey_index(struct sshkey *, int, struct ssh *);
|
||||
int sshd_hostkey_sign(struct sshkey *, struct sshkey *, u_char **,
|
||||
size_t *, const u_char *, size_t, const char *, u_int);
|
||||
|
||||
/* debug messages during authentication */
|
||||
void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-chall.c,v 1.44 2016/05/02 08:49:03 djm Exp $ */
|
||||
/* $OpenBSD: auth2-chall.c,v 1.48 2017/05/30 14:29:59 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2001 Per Allansson. All rights reserved.
|
||||
@ -47,9 +47,9 @@
|
||||
/* import */
|
||||
extern ServerOptions options;
|
||||
|
||||
static int auth2_challenge_start(Authctxt *);
|
||||
static int auth2_challenge_start(struct ssh *);
|
||||
static int send_userauth_info_request(Authctxt *);
|
||||
static int input_userauth_info_response(int, u_int32_t, void *);
|
||||
static int input_userauth_info_response(int, u_int32_t, struct ssh *);
|
||||
|
||||
#ifdef BSD_AUTH
|
||||
extern KbdintDevice bsdauth_device;
|
||||
@ -195,8 +195,9 @@ kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt)
|
||||
* wait for the response.
|
||||
*/
|
||||
int
|
||||
auth2_challenge(Authctxt *authctxt, char *devs)
|
||||
auth2_challenge(struct ssh *ssh, char *devs)
|
||||
{
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
debug("auth2_challenge: user=%s devs=%s",
|
||||
authctxt->user ? authctxt->user : "<nouser>",
|
||||
devs ? devs : "<no devs>");
|
||||
@ -205,15 +206,16 @@ auth2_challenge(Authctxt *authctxt, char *devs)
|
||||
return 0;
|
||||
if (authctxt->kbdintctxt == NULL)
|
||||
authctxt->kbdintctxt = kbdint_alloc(devs);
|
||||
return auth2_challenge_start(authctxt);
|
||||
return auth2_challenge_start(ssh);
|
||||
}
|
||||
|
||||
/* unregister kbd-int callbacks and context */
|
||||
void
|
||||
auth2_challenge_stop(Authctxt *authctxt)
|
||||
auth2_challenge_stop(struct ssh *ssh)
|
||||
{
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
/* unregister callback */
|
||||
dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE, NULL);
|
||||
if (authctxt->kbdintctxt != NULL) {
|
||||
kbdint_free(authctxt->kbdintctxt);
|
||||
authctxt->kbdintctxt = NULL;
|
||||
@ -222,29 +224,30 @@ auth2_challenge_stop(Authctxt *authctxt)
|
||||
|
||||
/* side effect: sets authctxt->postponed if a reply was sent*/
|
||||
static int
|
||||
auth2_challenge_start(Authctxt *authctxt)
|
||||
auth2_challenge_start(struct ssh *ssh)
|
||||
{
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
KbdintAuthctxt *kbdintctxt = authctxt->kbdintctxt;
|
||||
|
||||
debug2("auth2_challenge_start: devices %s",
|
||||
kbdintctxt->devices ? kbdintctxt->devices : "<empty>");
|
||||
|
||||
if (kbdint_next_device(authctxt, kbdintctxt) == 0) {
|
||||
auth2_challenge_stop(authctxt);
|
||||
auth2_challenge_stop(ssh);
|
||||
return 0;
|
||||
}
|
||||
debug("auth2_challenge_start: trying authentication method '%s'",
|
||||
kbdintctxt->device->name);
|
||||
|
||||
if ((kbdintctxt->ctxt = kbdintctxt->device->init_ctx(authctxt)) == NULL) {
|
||||
auth2_challenge_stop(authctxt);
|
||||
auth2_challenge_stop(ssh);
|
||||
return 0;
|
||||
}
|
||||
if (send_userauth_info_request(authctxt) == 0) {
|
||||
auth2_challenge_stop(authctxt);
|
||||
auth2_challenge_stop(ssh);
|
||||
return 0;
|
||||
}
|
||||
dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE,
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE,
|
||||
&input_userauth_info_response);
|
||||
|
||||
authctxt->postponed = 1;
|
||||
@ -285,9 +288,9 @@ send_userauth_info_request(Authctxt *authctxt)
|
||||
}
|
||||
|
||||
static int
|
||||
input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
|
||||
input_userauth_info_response(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
Authctxt *authctxt = ctxt;
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
KbdintAuthctxt *kbdintctxt;
|
||||
int authenticated = 0, res;
|
||||
u_int i, nresp;
|
||||
@ -340,14 +343,14 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
|
||||
devicename = kbdintctxt->device->name;
|
||||
if (!authctxt->postponed) {
|
||||
if (authenticated) {
|
||||
auth2_challenge_stop(authctxt);
|
||||
auth2_challenge_stop(ssh);
|
||||
} else {
|
||||
/* start next device */
|
||||
/* may set authctxt->postponed */
|
||||
auth2_challenge_start(authctxt);
|
||||
auth2_challenge_start(ssh);
|
||||
}
|
||||
}
|
||||
userauth_finish(authctxt, authenticated, "keyboard-interactive",
|
||||
userauth_finish(ssh, authenticated, "keyboard-interactive",
|
||||
devicename);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-gss.c,v 1.22 2015/01/19 20:07:45 markus Exp $ */
|
||||
/* $OpenBSD: auth2-gss.c,v 1.26 2017/06/24 06:34:38 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
|
||||
@ -48,18 +48,19 @@
|
||||
|
||||
extern ServerOptions options;
|
||||
|
||||
static int input_gssapi_token(int type, u_int32_t plen, void *ctxt);
|
||||
static int input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
|
||||
static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
|
||||
static int input_gssapi_errtok(int, u_int32_t, void *);
|
||||
static int input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh);
|
||||
static int input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh);
|
||||
static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh);
|
||||
static int input_gssapi_errtok(int, u_int32_t, struct ssh *);
|
||||
|
||||
/*
|
||||
* We only support those mechanisms that we know about (ie ones that we know
|
||||
* how to check local user kuserok and the like)
|
||||
*/
|
||||
static int
|
||||
userauth_gssapi(Authctxt *authctxt)
|
||||
userauth_gssapi(struct ssh *ssh)
|
||||
{
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
gss_OID_desc goid = {0, NULL};
|
||||
Gssctxt *ctxt = NULL;
|
||||
int mechs;
|
||||
@ -119,17 +120,17 @@ userauth_gssapi(Authctxt *authctxt)
|
||||
packet_send();
|
||||
free(doid);
|
||||
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
|
||||
authctxt->postponed = 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
input_gssapi_token(int type, u_int32_t plen, void *ctxt)
|
||||
input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh)
|
||||
{
|
||||
Authctxt *authctxt = ctxt;
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
Gssctxt *gssctxt;
|
||||
gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc recv_tok;
|
||||
@ -157,8 +158,8 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
|
||||
packet_send();
|
||||
}
|
||||
authctxt->postponed = 0;
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
userauth_finish(ssh, 0, "gssapi-with-mic", NULL);
|
||||
} else {
|
||||
if (send_tok.length != 0) {
|
||||
packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
|
||||
@ -166,12 +167,12 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
|
||||
packet_send();
|
||||
}
|
||||
if (maj_status == GSS_S_COMPLETE) {
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
if (flags & GSS_C_INTEG_FLAG)
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC,
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC,
|
||||
&input_gssapi_mic);
|
||||
else
|
||||
dispatch_set(
|
||||
ssh_dispatch_set(ssh,
|
||||
SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
|
||||
&input_gssapi_exchange_complete);
|
||||
}
|
||||
@ -182,9 +183,9 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
|
||||
}
|
||||
|
||||
static int
|
||||
input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
|
||||
input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh)
|
||||
{
|
||||
Authctxt *authctxt = ctxt;
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
Gssctxt *gssctxt;
|
||||
gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc recv_tok;
|
||||
@ -207,8 +208,8 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
|
||||
free(recv_tok.value);
|
||||
|
||||
/* We can't return anything to the client, even if we wanted to */
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
|
||||
|
||||
/* The client will have already moved on to the next auth */
|
||||
|
||||
@ -223,10 +224,11 @@ input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
|
||||
*/
|
||||
|
||||
static int
|
||||
input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
|
||||
input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh)
|
||||
{
|
||||
Authctxt *authctxt = ctxt;
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
int authenticated;
|
||||
const char *displayname;
|
||||
|
||||
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
|
||||
fatal("No authentication or GSSAPI context");
|
||||
@ -240,24 +242,29 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
|
||||
|
||||
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
|
||||
|
||||
if ((!use_privsep || mm_is_monitor()) &&
|
||||
(displayname = ssh_gssapi_displayname()) != NULL)
|
||||
auth2_record_info(authctxt, "%s", displayname);
|
||||
|
||||
authctxt->postponed = 0;
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
|
||||
userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
|
||||
userauth_finish(ssh, authenticated, "gssapi-with-mic", NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
|
||||
input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)
|
||||
{
|
||||
Authctxt *authctxt = ctxt;
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
Gssctxt *gssctxt;
|
||||
int authenticated = 0;
|
||||
Buffer b;
|
||||
gss_buffer_desc mic, gssbuf;
|
||||
u_int len;
|
||||
const char *displayname;
|
||||
|
||||
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
|
||||
fatal("No authentication or GSSAPI context");
|
||||
@ -281,12 +288,16 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
|
||||
buffer_free(&b);
|
||||
free(mic.value);
|
||||
|
||||
if ((!use_privsep || mm_is_monitor()) &&
|
||||
(displayname = ssh_gssapi_displayname()) != NULL)
|
||||
auth2_record_info(authctxt, "%s", displayname);
|
||||
|
||||
authctxt->postponed = 0;
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
|
||||
userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
|
||||
userauth_finish(ssh, authenticated, "gssapi-with-mic", NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-hostbased.c,v 1.26 2016/03/07 19:02:43 djm Exp $ */
|
||||
/* $OpenBSD: auth2-hostbased.c,v 1.31 2017/06/24 06:34:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -39,7 +39,7 @@
|
||||
#include "misc.h"
|
||||
#include "servconf.h"
|
||||
#include "compat.h"
|
||||
#include "key.h"
|
||||
#include "sshkey.h"
|
||||
#include "hostfile.h"
|
||||
#include "auth.h"
|
||||
#include "canohost.h"
|
||||
@ -48,6 +48,7 @@
|
||||
#endif
|
||||
#include "monitor_wrap.h"
|
||||
#include "pathnames.h"
|
||||
#include "ssherr.h"
|
||||
#include "match.h"
|
||||
|
||||
/* import */
|
||||
@ -56,54 +57,56 @@ extern u_char *session_id2;
|
||||
extern u_int session_id2_len;
|
||||
|
||||
static int
|
||||
userauth_hostbased(Authctxt *authctxt)
|
||||
userauth_hostbased(struct ssh *ssh)
|
||||
{
|
||||
Buffer b;
|
||||
Key *key = NULL;
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
struct sshbuf *b;
|
||||
struct sshkey *key = NULL;
|
||||
char *pkalg, *cuser, *chost, *service;
|
||||
u_char *pkblob, *sig;
|
||||
u_int alen, blen, slen;
|
||||
int pktype;
|
||||
int authenticated = 0;
|
||||
size_t alen, blen, slen;
|
||||
int r, pktype, authenticated = 0;
|
||||
|
||||
if (!authctxt->valid) {
|
||||
debug2("userauth_hostbased: disabled because of invalid user");
|
||||
debug2("%s: disabled because of invalid user", __func__);
|
||||
return 0;
|
||||
}
|
||||
pkalg = packet_get_string(&alen);
|
||||
pkblob = packet_get_string(&blen);
|
||||
chost = packet_get_string(NULL);
|
||||
cuser = packet_get_string(NULL);
|
||||
sig = packet_get_string(&slen);
|
||||
/* XXX use sshkey_froms() */
|
||||
if ((r = sshpkt_get_cstring(ssh, &pkalg, &alen)) != 0 ||
|
||||
(r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
|
||||
(r = sshpkt_get_cstring(ssh, &chost, NULL)) != 0 ||
|
||||
(r = sshpkt_get_cstring(ssh, &cuser, NULL)) != 0 ||
|
||||
(r = sshpkt_get_string(ssh, &sig, &slen)) != 0)
|
||||
fatal("%s: packet parsing: %s", __func__, ssh_err(r));
|
||||
|
||||
debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
|
||||
debug("%s: cuser %s chost %s pkalg %s slen %zu", __func__,
|
||||
cuser, chost, pkalg, slen);
|
||||
#ifdef DEBUG_PK
|
||||
debug("signature:");
|
||||
buffer_init(&b);
|
||||
buffer_append(&b, sig, slen);
|
||||
buffer_dump(&b);
|
||||
buffer_free(&b);
|
||||
sshbuf_dump_data(sig, siglen, stderr);
|
||||
#endif
|
||||
pktype = key_type_from_name(pkalg);
|
||||
pktype = sshkey_type_from_name(pkalg);
|
||||
if (pktype == KEY_UNSPEC) {
|
||||
/* this is perfectly legal */
|
||||
logit("userauth_hostbased: unsupported "
|
||||
"public key algorithm: %s", pkalg);
|
||||
logit("%s: unsupported public key algorithm: %s",
|
||||
__func__, pkalg);
|
||||
goto done;
|
||||
}
|
||||
if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
|
||||
error("%s: key_from_blob: %s", __func__, ssh_err(r));
|
||||
goto done;
|
||||
}
|
||||
key = key_from_blob(pkblob, blen);
|
||||
if (key == NULL) {
|
||||
error("userauth_hostbased: cannot decode key: %s", pkalg);
|
||||
error("%s: cannot decode key: %s", __func__, pkalg);
|
||||
goto done;
|
||||
}
|
||||
if (key->type != pktype) {
|
||||
error("userauth_hostbased: type mismatch for decoded key "
|
||||
"(received %d, expected %d)", key->type, pktype);
|
||||
error("%s: type mismatch for decoded key "
|
||||
"(received %d, expected %d)", __func__, key->type, pktype);
|
||||
goto done;
|
||||
}
|
||||
if (key_type_plain(key->type) == KEY_RSA &&
|
||||
(datafellows & SSH_BUG_RSASIGMD5) != 0) {
|
||||
if (sshkey_type_plain(key->type) == KEY_RSA &&
|
||||
(ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
|
||||
error("Refusing RSA key because peer uses unsafe "
|
||||
"signature format");
|
||||
goto done;
|
||||
@ -115,38 +118,40 @@ userauth_hostbased(Authctxt *authctxt)
|
||||
goto done;
|
||||
}
|
||||
|
||||
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
|
||||
service = ssh->compat & SSH_BUG_HBSERVICE ? "ssh-userauth" :
|
||||
authctxt->service;
|
||||
buffer_init(&b);
|
||||
buffer_put_string(&b, session_id2, session_id2_len);
|
||||
if ((b = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
/* reconstruct packet */
|
||||
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
|
||||
buffer_put_cstring(&b, authctxt->user);
|
||||
buffer_put_cstring(&b, service);
|
||||
buffer_put_cstring(&b, "hostbased");
|
||||
buffer_put_string(&b, pkalg, alen);
|
||||
buffer_put_string(&b, pkblob, blen);
|
||||
buffer_put_cstring(&b, chost);
|
||||
buffer_put_cstring(&b, cuser);
|
||||
if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
|
||||
(r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, authctxt->user)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, service)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, "hostbased")) != 0 ||
|
||||
(r = sshbuf_put_string(b, pkalg, alen)) != 0 ||
|
||||
(r = sshbuf_put_string(b, pkblob, blen)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, chost)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, cuser)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
#ifdef DEBUG_PK
|
||||
buffer_dump(&b);
|
||||
sshbuf_dump(b, stderr);
|
||||
#endif
|
||||
|
||||
pubkey_auth_info(authctxt, key,
|
||||
auth2_record_info(authctxt,
|
||||
"client user \"%.100s\", client host \"%.100s\"", cuser, chost);
|
||||
|
||||
/* test for allowed key and correct signature */
|
||||
authenticated = 0;
|
||||
if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
|
||||
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
|
||||
buffer_len(&b))) == 1)
|
||||
PRIVSEP(sshkey_verify(key, sig, slen,
|
||||
sshbuf_ptr(b), sshbuf_len(b), ssh->compat)) == 0)
|
||||
authenticated = 1;
|
||||
|
||||
buffer_free(&b);
|
||||
auth2_record_key(authctxt, authenticated, key);
|
||||
sshbuf_free(b);
|
||||
done:
|
||||
debug2("userauth_hostbased: authenticated %d", authenticated);
|
||||
if (key != NULL)
|
||||
key_free(key);
|
||||
debug2("%s: authenticated %d", __func__, authenticated);
|
||||
sshkey_free(key);
|
||||
free(pkalg);
|
||||
free(pkblob);
|
||||
free(cuser);
|
||||
@ -158,7 +163,7 @@ userauth_hostbased(Authctxt *authctxt)
|
||||
/* return 1 if given hostkey is allowed */
|
||||
int
|
||||
hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
|
||||
Key *key)
|
||||
struct sshkey *key)
|
||||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
const char *resolvedname, *ipaddr, *lookup, *reason;
|
||||
@ -203,8 +208,8 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
|
||||
}
|
||||
debug2("%s: access allowed by auth_rhosts2", __func__);
|
||||
|
||||
if (key_is_cert(key) &&
|
||||
key_cert_check_authority(key, 1, 0, lookup, &reason)) {
|
||||
if (sshkey_is_cert(key) &&
|
||||
sshkey_cert_check_authority(key, 1, 0, lookup, &reason)) {
|
||||
error("%s", reason);
|
||||
auth_debug_add("%s", reason);
|
||||
return 0;
|
||||
@ -223,20 +228,20 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
|
||||
}
|
||||
|
||||
if (host_status == HOST_OK) {
|
||||
if (key_is_cert(key)) {
|
||||
if (sshkey_is_cert(key)) {
|
||||
if ((fp = sshkey_fingerprint(key->cert->signature_key,
|
||||
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
|
||||
fatal("%s: sshkey_fingerprint fail", __func__);
|
||||
verbose("Accepted certificate ID \"%s\" signed by "
|
||||
"%s CA %s from %s@%s", key->cert->key_id,
|
||||
key_type(key->cert->signature_key), fp,
|
||||
sshkey_type(key->cert->signature_key), fp,
|
||||
cuser, lookup);
|
||||
} else {
|
||||
if ((fp = sshkey_fingerprint(key,
|
||||
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
|
||||
fatal("%s: sshkey_fingerprint fail", __func__);
|
||||
verbose("Accepted %s public key %s from %s@%s",
|
||||
key_type(key), fp, cuser, lookup);
|
||||
sshkey_type(key), fp, cuser, lookup);
|
||||
}
|
||||
free(fp);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */
|
||||
/* $OpenBSD: auth2-kbdint.c,v 1.8 2017/05/30 14:29:59 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -43,7 +43,7 @@
|
||||
extern ServerOptions options;
|
||||
|
||||
static int
|
||||
userauth_kbdint(Authctxt *authctxt)
|
||||
userauth_kbdint(struct ssh *ssh)
|
||||
{
|
||||
int authenticated = 0;
|
||||
char *lang, *devs;
|
||||
@ -55,7 +55,7 @@ userauth_kbdint(Authctxt *authctxt)
|
||||
debug("keyboard-interactive devs %s", devs);
|
||||
|
||||
if (options.challenge_response_authentication)
|
||||
authenticated = auth2_challenge(authctxt, devs);
|
||||
authenticated = auth2_challenge(ssh, devs);
|
||||
|
||||
free(devs);
|
||||
free(lang);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
|
||||
/* $OpenBSD: auth2-none.c,v 1.20 2017/05/30 14:29:59 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -37,7 +37,7 @@
|
||||
|
||||
#include "atomicio.h"
|
||||
#include "xmalloc.h"
|
||||
#include "key.h"
|
||||
#include "sshkey.h"
|
||||
#include "hostfile.h"
|
||||
#include "auth.h"
|
||||
#include "packet.h"
|
||||
@ -47,6 +47,7 @@
|
||||
#include "servconf.h"
|
||||
#include "compat.h"
|
||||
#include "ssh2.h"
|
||||
#include "ssherr.h"
|
||||
#ifdef GSSAPI
|
||||
#include "ssh-gss.h"
|
||||
#endif
|
||||
@ -59,12 +60,15 @@ extern ServerOptions options;
|
||||
static int none_enabled = 1;
|
||||
|
||||
static int
|
||||
userauth_none(Authctxt *authctxt)
|
||||
userauth_none(struct ssh *ssh)
|
||||
{
|
||||
int r;
|
||||
|
||||
none_enabled = 0;
|
||||
packet_check_eom();
|
||||
if ((r = sshpkt_get_end(ssh)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
if (options.permit_empty_passwd && options.password_authentication)
|
||||
return (PRIVSEP(auth_password(authctxt, "")));
|
||||
return (PRIVSEP(auth_password(ssh->authctxt, "")));
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */
|
||||
/* $OpenBSD: auth2-passwd.c,v 1.14 2017/05/30 14:29:59 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -30,10 +30,10 @@
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "packet.h"
|
||||
#include "ssherr.h"
|
||||
#include "log.h"
|
||||
#include "key.h"
|
||||
#include "sshkey.h"
|
||||
#include "hostfile.h"
|
||||
#include "auth.h"
|
||||
#include "buffer.h"
|
||||
@ -48,26 +48,22 @@
|
||||
extern ServerOptions options;
|
||||
|
||||
static int
|
||||
userauth_passwd(Authctxt *authctxt)
|
||||
userauth_passwd(struct ssh *ssh)
|
||||
{
|
||||
char *password, *newpass;
|
||||
int authenticated = 0;
|
||||
int change;
|
||||
u_int len, newlen;
|
||||
char *password;
|
||||
int authenticated = 0, r;
|
||||
u_char change;
|
||||
size_t len;
|
||||
|
||||
change = packet_get_char();
|
||||
password = packet_get_string(&len);
|
||||
if (change) {
|
||||
/* discard new password from packet */
|
||||
newpass = packet_get_string(&newlen);
|
||||
explicit_bzero(newpass, newlen);
|
||||
free(newpass);
|
||||
}
|
||||
packet_check_eom();
|
||||
if ((r = sshpkt_get_u8(ssh, &change)) != 0 ||
|
||||
(r = sshpkt_get_cstring(ssh, &password, &len)) != 0 ||
|
||||
(change && (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) ||
|
||||
(r = sshpkt_get_end(ssh)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
|
||||
if (change)
|
||||
logit("password change not supported");
|
||||
else if (PRIVSEP(auth_password(authctxt, password)) == 1)
|
||||
else if (PRIVSEP(auth_password(ssh->authctxt, password)) == 1)
|
||||
authenticated = 1;
|
||||
explicit_bzero(password, len);
|
||||
free(password);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-pubkey.c,v 1.62 2017/01/30 01:03:00 djm Exp $ */
|
||||
/* $OpenBSD: auth2-pubkey.c,v 1.71 2017/09/07 23:48:09 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -27,7 +27,6 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@ -52,7 +51,7 @@
|
||||
#include "misc.h"
|
||||
#include "servconf.h"
|
||||
#include "compat.h"
|
||||
#include "key.h"
|
||||
#include "sshkey.h"
|
||||
#include "hostfile.h"
|
||||
#include "auth.h"
|
||||
#include "pathnames.h"
|
||||
@ -75,42 +74,52 @@ extern u_char *session_id2;
|
||||
extern u_int session_id2_len;
|
||||
|
||||
static int
|
||||
userauth_pubkey(Authctxt *authctxt)
|
||||
userauth_pubkey(struct ssh *ssh)
|
||||
{
|
||||
Buffer b;
|
||||
Key *key = NULL;
|
||||
char *pkalg, *userstyle, *fp = NULL;
|
||||
u_char *pkblob, *sig;
|
||||
u_int alen, blen, slen;
|
||||
int have_sig, pktype;
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
struct sshbuf *b;
|
||||
struct sshkey *key = NULL;
|
||||
char *pkalg, *userstyle = NULL, *fp = NULL;
|
||||
u_char *pkblob, *sig, have_sig;
|
||||
size_t blen, slen;
|
||||
int r, pktype;
|
||||
int authenticated = 0;
|
||||
|
||||
if (!authctxt->valid) {
|
||||
debug2("%s: disabled because of invalid user", __func__);
|
||||
return 0;
|
||||
}
|
||||
have_sig = packet_get_char();
|
||||
if (datafellows & SSH_BUG_PKAUTH) {
|
||||
if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0)
|
||||
fatal("%s: sshpkt_get_u8 failed: %s", __func__, ssh_err(r));
|
||||
if (ssh->compat & SSH_BUG_PKAUTH) {
|
||||
debug2("%s: SSH_BUG_PKAUTH", __func__);
|
||||
if ((b = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
/* no explicit pkalg given */
|
||||
pkblob = packet_get_string(&blen);
|
||||
buffer_init(&b);
|
||||
buffer_append(&b, pkblob, blen);
|
||||
/* so we have to extract the pkalg from the pkblob */
|
||||
pkalg = buffer_get_string(&b, &alen);
|
||||
buffer_free(&b);
|
||||
/* XXX use sshbuf_from() */
|
||||
if ((r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
|
||||
(r = sshbuf_put(b, pkblob, blen)) != 0 ||
|
||||
(r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0)
|
||||
fatal("%s: failed: %s", __func__, ssh_err(r));
|
||||
sshbuf_free(b);
|
||||
} else {
|
||||
pkalg = packet_get_string(&alen);
|
||||
pkblob = packet_get_string(&blen);
|
||||
if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
|
||||
(r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0)
|
||||
fatal("%s: sshpkt_get_cstring failed: %s",
|
||||
__func__, ssh_err(r));
|
||||
}
|
||||
pktype = key_type_from_name(pkalg);
|
||||
pktype = sshkey_type_from_name(pkalg);
|
||||
if (pktype == KEY_UNSPEC) {
|
||||
/* this is perfectly legal */
|
||||
logit("%s: unsupported public key algorithm: %s",
|
||||
__func__, pkalg);
|
||||
goto done;
|
||||
}
|
||||
key = key_from_blob(pkblob, blen);
|
||||
if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
|
||||
error("%s: could not parse key: %s", __func__, ssh_err(r));
|
||||
goto done;
|
||||
}
|
||||
if (key == NULL) {
|
||||
error("%s: cannot decode key: %s", __func__, pkalg);
|
||||
goto done;
|
||||
@ -120,15 +129,15 @@ userauth_pubkey(Authctxt *authctxt)
|
||||
"(received %d, expected %d)", __func__, key->type, pktype);
|
||||
goto done;
|
||||
}
|
||||
if (key_type_plain(key->type) == KEY_RSA &&
|
||||
(datafellows & SSH_BUG_RSASIGMD5) != 0) {
|
||||
if (sshkey_type_plain(key->type) == KEY_RSA &&
|
||||
(ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
|
||||
logit("Refusing RSA key because client uses unsafe "
|
||||
"signature scheme");
|
||||
goto done;
|
||||
}
|
||||
fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
|
||||
if (auth2_userkey_already_used(authctxt, key)) {
|
||||
logit("refusing previously-used %s key", key_type(key));
|
||||
if (auth2_key_already_used(authctxt, key)) {
|
||||
logit("refusing previously-used %s key", sshkey_type(key));
|
||||
goto done;
|
||||
}
|
||||
if (match_pattern_list(sshkey_ssh_name(key),
|
||||
@ -141,54 +150,65 @@ userauth_pubkey(Authctxt *authctxt)
|
||||
if (have_sig) {
|
||||
debug3("%s: have signature for %s %s",
|
||||
__func__, sshkey_type(key), fp);
|
||||
sig = packet_get_string(&slen);
|
||||
packet_check_eom();
|
||||
buffer_init(&b);
|
||||
if (datafellows & SSH_OLD_SESSIONID) {
|
||||
buffer_append(&b, session_id2, session_id2_len);
|
||||
if ((r = sshpkt_get_string(ssh, &sig, &slen)) != 0 ||
|
||||
(r = sshpkt_get_end(ssh)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
if ((b = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
if (ssh->compat & SSH_OLD_SESSIONID) {
|
||||
if ((r = sshbuf_put(b, session_id2,
|
||||
session_id2_len)) != 0)
|
||||
fatal("%s: sshbuf_put session id: %s",
|
||||
__func__, ssh_err(r));
|
||||
} else {
|
||||
buffer_put_string(&b, session_id2, session_id2_len);
|
||||
if ((r = sshbuf_put_string(b, session_id2,
|
||||
session_id2_len)) != 0)
|
||||
fatal("%s: sshbuf_put_string session id: %s",
|
||||
__func__, ssh_err(r));
|
||||
}
|
||||
/* reconstruct packet */
|
||||
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
|
||||
xasprintf(&userstyle, "%s%s%s", authctxt->user,
|
||||
authctxt->style ? ":" : "",
|
||||
authctxt->style ? authctxt->style : "");
|
||||
buffer_put_cstring(&b, userstyle);
|
||||
free(userstyle);
|
||||
buffer_put_cstring(&b,
|
||||
datafellows & SSH_BUG_PKSERVICE ?
|
||||
"ssh-userauth" :
|
||||
authctxt->service);
|
||||
if (datafellows & SSH_BUG_PKAUTH) {
|
||||
buffer_put_char(&b, have_sig);
|
||||
if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, userstyle)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, ssh->compat & SSH_BUG_PKSERVICE ?
|
||||
"ssh-userauth" : authctxt->service)) != 0)
|
||||
fatal("%s: build packet failed: %s",
|
||||
__func__, ssh_err(r));
|
||||
if (ssh->compat & SSH_BUG_PKAUTH) {
|
||||
if ((r = sshbuf_put_u8(b, have_sig)) != 0)
|
||||
fatal("%s: build packet failed: %s",
|
||||
__func__, ssh_err(r));
|
||||
} else {
|
||||
buffer_put_cstring(&b, "publickey");
|
||||
buffer_put_char(&b, have_sig);
|
||||
buffer_put_cstring(&b, pkalg);
|
||||
if ((r = sshbuf_put_cstring(b, "publickey")) != 0 ||
|
||||
(r = sshbuf_put_u8(b, have_sig)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, pkalg) != 0))
|
||||
fatal("%s: build packet failed: %s",
|
||||
__func__, ssh_err(r));
|
||||
}
|
||||
buffer_put_string(&b, pkblob, blen);
|
||||
if ((r = sshbuf_put_string(b, pkblob, blen)) != 0)
|
||||
fatal("%s: build packet failed: %s",
|
||||
__func__, ssh_err(r));
|
||||
#ifdef DEBUG_PK
|
||||
buffer_dump(&b);
|
||||
sshbuf_dump(b, stderr);
|
||||
#endif
|
||||
pubkey_auth_info(authctxt, key, NULL);
|
||||
|
||||
/* test for correct signature */
|
||||
authenticated = 0;
|
||||
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
|
||||
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
|
||||
buffer_len(&b))) == 1) {
|
||||
PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
|
||||
sshbuf_len(b), ssh->compat)) == 0) {
|
||||
authenticated = 1;
|
||||
/* Record the successful key to prevent reuse */
|
||||
auth2_record_userkey(authctxt, key);
|
||||
key = NULL; /* Don't free below */
|
||||
}
|
||||
buffer_free(&b);
|
||||
sshbuf_free(b);
|
||||
free(sig);
|
||||
auth2_record_key(authctxt, authenticated, key);
|
||||
} else {
|
||||
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
|
||||
__func__, sshkey_type(key), fp);
|
||||
packet_check_eom();
|
||||
if ((r = sshpkt_get_end(ssh)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
|
||||
/* XXX fake reply and always send PK_OK ? */
|
||||
/*
|
||||
@ -199,11 +219,13 @@ userauth_pubkey(Authctxt *authctxt)
|
||||
* issue? -markus
|
||||
*/
|
||||
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) {
|
||||
packet_start(SSH2_MSG_USERAUTH_PK_OK);
|
||||
packet_put_string(pkalg, alen);
|
||||
packet_put_string(pkblob, blen);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK))
|
||||
!= 0 ||
|
||||
(r = sshpkt_put_cstring(ssh, pkalg)) != 0 ||
|
||||
(r = sshpkt_put_string(ssh, pkblob, blen)) != 0 ||
|
||||
(r = sshpkt_send(ssh)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
ssh_packet_write_wait(ssh);
|
||||
authctxt->postponed = 1;
|
||||
}
|
||||
}
|
||||
@ -211,333 +233,14 @@ userauth_pubkey(Authctxt *authctxt)
|
||||
auth_clear_options();
|
||||
done:
|
||||
debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
|
||||
if (key != NULL)
|
||||
key_free(key);
|
||||
sshkey_free(key);
|
||||
free(userstyle);
|
||||
free(pkalg);
|
||||
free(pkblob);
|
||||
free(fp);
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
void
|
||||
pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
|
||||
{
|
||||
char *fp, *extra;
|
||||
va_list ap;
|
||||
int i;
|
||||
|
||||
extra = NULL;
|
||||
if (fmt != NULL) {
|
||||
va_start(ap, fmt);
|
||||
i = vasprintf(&extra, fmt, ap);
|
||||
va_end(ap);
|
||||
if (i < 0 || extra == NULL)
|
||||
fatal("%s: vasprintf failed", __func__);
|
||||
}
|
||||
|
||||
if (key_is_cert(key)) {
|
||||
fp = sshkey_fingerprint(key->cert->signature_key,
|
||||
options.fingerprint_hash, SSH_FP_DEFAULT);
|
||||
auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
|
||||
key_type(key), key->cert->key_id,
|
||||
(unsigned long long)key->cert->serial,
|
||||
key_type(key->cert->signature_key),
|
||||
fp == NULL ? "(null)" : fp,
|
||||
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
|
||||
free(fp);
|
||||
} else {
|
||||
fp = sshkey_fingerprint(key, options.fingerprint_hash,
|
||||
SSH_FP_DEFAULT);
|
||||
auth_info(authctxt, "%s %s%s%s", key_type(key),
|
||||
fp == NULL ? "(null)" : fp,
|
||||
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
|
||||
free(fp);
|
||||
}
|
||||
free(extra);
|
||||
}
|
||||
|
||||
/*
|
||||
* Splits 's' into an argument vector. Handles quoted string and basic
|
||||
* escape characters (\\, \", \'). Caller must free the argument vector
|
||||
* and its members.
|
||||
*/
|
||||
static int
|
||||
split_argv(const char *s, int *argcp, char ***argvp)
|
||||
{
|
||||
int r = SSH_ERR_INTERNAL_ERROR;
|
||||
int argc = 0, quote, i, j;
|
||||
char *arg, **argv = xcalloc(1, sizeof(*argv));
|
||||
|
||||
*argvp = NULL;
|
||||
*argcp = 0;
|
||||
|
||||
for (i = 0; s[i] != '\0'; i++) {
|
||||
/* Skip leading whitespace */
|
||||
if (s[i] == ' ' || s[i] == '\t')
|
||||
continue;
|
||||
|
||||
/* Start of a token */
|
||||
quote = 0;
|
||||
if (s[i] == '\\' &&
|
||||
(s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\'))
|
||||
i++;
|
||||
else if (s[i] == '\'' || s[i] == '"')
|
||||
quote = s[i++];
|
||||
|
||||
argv = xreallocarray(argv, (argc + 2), sizeof(*argv));
|
||||
arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1);
|
||||
argv[argc] = NULL;
|
||||
|
||||
/* Copy the token in, removing escapes */
|
||||
for (j = 0; s[i] != '\0'; i++) {
|
||||
if (s[i] == '\\') {
|
||||
if (s[i + 1] == '\'' ||
|
||||
s[i + 1] == '\"' ||
|
||||
s[i + 1] == '\\') {
|
||||
i++; /* Skip '\' */
|
||||
arg[j++] = s[i];
|
||||
} else {
|
||||
/* Unrecognised escape */
|
||||
arg[j++] = s[i];
|
||||
}
|
||||
} else if (quote == 0 && (s[i] == ' ' || s[i] == '\t'))
|
||||
break; /* done */
|
||||
else if (quote != 0 && s[i] == quote)
|
||||
break; /* done */
|
||||
else
|
||||
arg[j++] = s[i];
|
||||
}
|
||||
if (s[i] == '\0') {
|
||||
if (quote != 0) {
|
||||
/* Ran out of string looking for close quote */
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Success */
|
||||
*argcp = argc;
|
||||
*argvp = argv;
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
r = 0;
|
||||
out:
|
||||
if (argc != 0 && argv != NULL) {
|
||||
for (i = 0; i < argc; i++)
|
||||
free(argv[i]);
|
||||
free(argv);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reassemble an argument vector into a string, quoting and escaping as
|
||||
* necessary. Caller must free returned string.
|
||||
*/
|
||||
static char *
|
||||
assemble_argv(int argc, char **argv)
|
||||
{
|
||||
int i, j, ws, r;
|
||||
char c, *ret;
|
||||
struct sshbuf *buf, *arg;
|
||||
|
||||
if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
ws = 0;
|
||||
sshbuf_reset(arg);
|
||||
for (j = 0; argv[i][j] != '\0'; j++) {
|
||||
r = 0;
|
||||
c = argv[i][j];
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
ws = 1;
|
||||
r = sshbuf_put_u8(arg, c);
|
||||
break;
|
||||
case '\\':
|
||||
case '\'':
|
||||
case '"':
|
||||
if ((r = sshbuf_put_u8(arg, '\\')) != 0)
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
r = sshbuf_put_u8(arg, c);
|
||||
break;
|
||||
}
|
||||
if (r != 0)
|
||||
fatal("%s: sshbuf_put_u8: %s",
|
||||
__func__, ssh_err(r));
|
||||
}
|
||||
if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) ||
|
||||
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) ||
|
||||
(r = sshbuf_putb(buf, arg)) != 0 ||
|
||||
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0))
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
}
|
||||
if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL)
|
||||
fatal("%s: malloc failed", __func__);
|
||||
memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf));
|
||||
ret[sshbuf_len(buf)] = '\0';
|
||||
sshbuf_free(buf);
|
||||
sshbuf_free(arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs command in a subprocess. Returns pid on success and a FILE* to the
|
||||
* subprocess' stdout or 0 on failure.
|
||||
* NB. "command" is only used for logging.
|
||||
*/
|
||||
static pid_t
|
||||
subprocess(const char *tag, struct passwd *pw, const char *command,
|
||||
int ac, char **av, FILE **child)
|
||||
{
|
||||
FILE *f;
|
||||
struct stat st;
|
||||
int devnull, p[2], i;
|
||||
pid_t pid;
|
||||
char *cp, errmsg[512];
|
||||
u_int envsize;
|
||||
char **child_env;
|
||||
|
||||
*child = NULL;
|
||||
|
||||
debug3("%s: %s command \"%s\" running as %s", __func__,
|
||||
tag, command, pw->pw_name);
|
||||
|
||||
/* Verify the path exists and is safe-ish to execute */
|
||||
if (*av[0] != '/') {
|
||||
error("%s path is not absolute", tag);
|
||||
return 0;
|
||||
}
|
||||
temporarily_use_uid(pw);
|
||||
if (stat(av[0], &st) < 0) {
|
||||
error("Could not stat %s \"%s\": %s", tag,
|
||||
av[0], strerror(errno));
|
||||
restore_uid();
|
||||
return 0;
|
||||
}
|
||||
if (auth_secure_path(av[0], &st, NULL, 0,
|
||||
errmsg, sizeof(errmsg)) != 0) {
|
||||
error("Unsafe %s \"%s\": %s", tag, av[0], errmsg);
|
||||
restore_uid();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run the command; stderr is left in place, stdout is the
|
||||
* authorized_keys output.
|
||||
*/
|
||||
if (pipe(p) != 0) {
|
||||
error("%s: pipe: %s", tag, strerror(errno));
|
||||
restore_uid();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't want to call this in the child, where it can fatal() and
|
||||
* run cleanup_exit() code.
|
||||
*/
|
||||
restore_uid();
|
||||
|
||||
switch ((pid = fork())) {
|
||||
case -1: /* error */
|
||||
error("%s: fork: %s", tag, strerror(errno));
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
return 0;
|
||||
case 0: /* child */
|
||||
/* Prepare a minimal environment for the child. */
|
||||
envsize = 5;
|
||||
child_env = xcalloc(sizeof(*child_env), envsize);
|
||||
child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH);
|
||||
child_set_env(&child_env, &envsize, "USER", pw->pw_name);
|
||||
child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name);
|
||||
child_set_env(&child_env, &envsize, "HOME", pw->pw_dir);
|
||||
if ((cp = getenv("LANG")) != NULL)
|
||||
child_set_env(&child_env, &envsize, "LANG", cp);
|
||||
|
||||
for (i = 0; i < NSIG; i++)
|
||||
signal(i, SIG_DFL);
|
||||
|
||||
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
|
||||
error("%s: open %s: %s", tag, _PATH_DEVNULL,
|
||||
strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
/* Keep stderr around a while longer to catch errors */
|
||||
if (dup2(devnull, STDIN_FILENO) == -1 ||
|
||||
dup2(p[1], STDOUT_FILENO) == -1) {
|
||||
error("%s: dup2: %s", tag, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
|
||||
/* Don't use permanently_set_uid() here to avoid fatal() */
|
||||
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
|
||||
error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
|
||||
strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
|
||||
error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid,
|
||||
strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
/* stdin is pointed to /dev/null at this point */
|
||||
if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
|
||||
error("%s: dup2: %s", tag, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
execve(av[0], av, child_env);
|
||||
error("%s exec \"%s\": %s", tag, command, strerror(errno));
|
||||
_exit(127);
|
||||
default: /* parent */
|
||||
break;
|
||||
}
|
||||
|
||||
close(p[1]);
|
||||
if ((f = fdopen(p[0], "r")) == NULL) {
|
||||
error("%s: fdopen: %s", tag, strerror(errno));
|
||||
close(p[0]);
|
||||
/* Don't leave zombie child */
|
||||
kill(pid, SIGTERM);
|
||||
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
/* Success */
|
||||
debug3("%s: %s pid %ld", __func__, tag, (long)pid);
|
||||
*child = f;
|
||||
return pid;
|
||||
}
|
||||
|
||||
/* Returns 0 if pid exited cleanly, non-zero otherwise */
|
||||
static int
|
||||
exited_cleanly(pid_t pid, const char *tag, const char *cmd)
|
||||
{
|
||||
int status;
|
||||
|
||||
while (waitpid(pid, &status, 0) == -1) {
|
||||
if (errno != EINTR) {
|
||||
error("%s: waitpid: %s", tag, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (WIFSIGNALED(status)) {
|
||||
error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status));
|
||||
return -1;
|
||||
} else if (WEXITSTATUS(status) != 0) {
|
||||
error("%s %s failed, status %d", tag, cmd, WEXITSTATUS(status));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
match_principals_option(const char *principal_list, struct sshkey_cert *cert)
|
||||
{
|
||||
@ -559,7 +262,7 @@ match_principals_option(const char *principal_list, struct sshkey_cert *cert)
|
||||
}
|
||||
|
||||
static int
|
||||
process_principals(FILE *f, char *file, struct passwd *pw,
|
||||
process_principals(FILE *f, const char *file, struct passwd *pw,
|
||||
const struct sshkey_cert *cert)
|
||||
{
|
||||
char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
|
||||
@ -597,8 +300,7 @@ process_principals(FILE *f, char *file, struct passwd *pw,
|
||||
for (i = 0; i < cert->nprincipals; i++) {
|
||||
if (strcmp(cp, cert->principals[i]) == 0) {
|
||||
debug3("%s:%lu: matched principal \"%.100s\"",
|
||||
file == NULL ? "(command)" : file,
|
||||
linenum, cert->principals[i]);
|
||||
file, linenum, cert->principals[i]);
|
||||
if (auth_parse_options(pw, line_opts,
|
||||
file, linenum) != 1)
|
||||
continue;
|
||||
@ -671,7 +373,7 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
|
||||
}
|
||||
|
||||
/* Turn the command into an argument vector */
|
||||
if (split_argv(options.authorized_principals_command, &ac, &av) != 0) {
|
||||
if (argv_split(options.authorized_principals_command, &ac, &av) != 0) {
|
||||
error("AuthorizedPrincipalsCommand \"%s\" contains "
|
||||
"invalid quotes", command);
|
||||
goto out;
|
||||
@ -720,21 +422,22 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
|
||||
av[i] = tmp;
|
||||
}
|
||||
/* Prepare a printable command for logs, etc. */
|
||||
command = assemble_argv(ac, av);
|
||||
command = argv_assemble(ac, av);
|
||||
|
||||
if ((pid = subprocess("AuthorizedPrincipalsCommand", pw, command,
|
||||
ac, av, &f)) == 0)
|
||||
ac, av, &f,
|
||||
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
|
||||
goto out;
|
||||
|
||||
uid_swapped = 1;
|
||||
temporarily_use_uid(pw);
|
||||
|
||||
ok = process_principals(f, NULL, pw, cert);
|
||||
ok = process_principals(f, "(command)", pw, cert);
|
||||
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
|
||||
if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command) != 0)
|
||||
if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command, 0) != 0)
|
||||
goto out;
|
||||
|
||||
/* Read completed successfully */
|
||||
@ -761,26 +464,25 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
|
||||
* returns 1 if the key is allowed or 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
check_authkeys_file(FILE *f, char *file, struct sshkey *key, struct passwd *pw)
|
||||
{
|
||||
char line[SSH_MAX_PUBKEY_BYTES];
|
||||
int found_key = 0;
|
||||
u_long linenum = 0;
|
||||
Key *found;
|
||||
struct sshkey *found = NULL;
|
||||
|
||||
found_key = 0;
|
||||
|
||||
found = NULL;
|
||||
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
|
||||
char *cp, *key_options = NULL, *fp = NULL;
|
||||
const char *reason = NULL;
|
||||
|
||||
/* Always consume entrire file */
|
||||
/* Always consume entire file */
|
||||
if (found_key)
|
||||
continue;
|
||||
if (found != NULL)
|
||||
key_free(found);
|
||||
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
|
||||
sshkey_free(found);
|
||||
found = sshkey_new(sshkey_is_cert(key) ? KEY_UNSPEC : key->type);
|
||||
if (found == NULL)
|
||||
goto done;
|
||||
auth_clear_options();
|
||||
|
||||
/* Skip leading whitespace, empty and comment lines. */
|
||||
@ -789,7 +491,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
if (!*cp || *cp == '\n' || *cp == '#')
|
||||
continue;
|
||||
|
||||
if (key_read(found, &cp) != 1) {
|
||||
if (sshkey_read(found, &cp) != 0) {
|
||||
/* no key? check if there are options for this key */
|
||||
int quoted = 0;
|
||||
debug2("user_key_allowed: check options: '%s'", cp);
|
||||
@ -803,14 +505,14 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
/* Skip remaining whitespace. */
|
||||
for (; *cp == ' ' || *cp == '\t'; cp++)
|
||||
;
|
||||
if (key_read(found, &cp) != 1) {
|
||||
if (sshkey_read(found, &cp) != 0) {
|
||||
debug2("user_key_allowed: advance: '%s'", cp);
|
||||
/* still no key? advance to next line*/
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (key_is_cert(key)) {
|
||||
if (!key_equal(found, key->cert->signature_key))
|
||||
if (sshkey_is_cert(key)) {
|
||||
if (!sshkey_equal(found, key->cert->signature_key))
|
||||
continue;
|
||||
if (auth_parse_options(pw, key_options, file,
|
||||
linenum) != 1)
|
||||
@ -821,7 +523,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
|
||||
continue;
|
||||
debug("matching CA found: file %s, line %lu, %s %s",
|
||||
file, linenum, key_type(found), fp);
|
||||
file, linenum, sshkey_type(found), fp);
|
||||
/*
|
||||
* If the user has specified a list of principals as
|
||||
* a key option, then prefer that list to matching
|
||||
@ -838,7 +540,7 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
auth_debug_add("%s", reason);
|
||||
continue;
|
||||
}
|
||||
if (key_cert_check_authority(key, 0, 0,
|
||||
if (sshkey_cert_check_authority(key, 0, 0,
|
||||
authorized_principals == NULL ? pw->pw_name : NULL,
|
||||
&reason) != 0)
|
||||
goto fail_reason;
|
||||
@ -847,11 +549,11 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
verbose("Accepted certificate ID \"%s\" (serial %llu) "
|
||||
"signed by %s CA %s via %s", key->cert->key_id,
|
||||
(unsigned long long)key->cert->serial,
|
||||
key_type(found), fp, file);
|
||||
sshkey_type(found), fp, file);
|
||||
free(fp);
|
||||
found_key = 1;
|
||||
break;
|
||||
} else if (key_equal(found, key)) {
|
||||
} else if (sshkey_equal(found, key)) {
|
||||
if (auth_parse_options(pw, key_options, file,
|
||||
linenum) != 1)
|
||||
continue;
|
||||
@ -861,14 +563,15 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
|
||||
continue;
|
||||
debug("matching key found: file %s, line %lu %s %s",
|
||||
file, linenum, key_type(found), fp);
|
||||
file, linenum, sshkey_type(found), fp);
|
||||
free(fp);
|
||||
found_key = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (found != NULL)
|
||||
key_free(found);
|
||||
sshkey_free(found);
|
||||
if (!found_key)
|
||||
debug2("key not found");
|
||||
return found_key;
|
||||
@ -876,24 +579,24 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
|
||||
/* Authenticate a certificate key against TrustedUserCAKeys */
|
||||
static int
|
||||
user_cert_trusted_ca(struct passwd *pw, Key *key)
|
||||
user_cert_trusted_ca(struct passwd *pw, struct sshkey *key)
|
||||
{
|
||||
char *ca_fp, *principals_file = NULL;
|
||||
const char *reason;
|
||||
int ret = 0, found_principal = 0, use_authorized_principals;
|
||||
int r, ret = 0, found_principal = 0, use_authorized_principals;
|
||||
|
||||
if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
|
||||
if (!sshkey_is_cert(key) || options.trusted_user_ca_keys == NULL)
|
||||
return 0;
|
||||
|
||||
if ((ca_fp = sshkey_fingerprint(key->cert->signature_key,
|
||||
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
|
||||
return 0;
|
||||
|
||||
if (sshkey_in_file(key->cert->signature_key,
|
||||
options.trusted_user_ca_keys, 1, 0) != 0) {
|
||||
debug2("%s: CA %s %s is not listed in %s", __func__,
|
||||
key_type(key->cert->signature_key), ca_fp,
|
||||
options.trusted_user_ca_keys);
|
||||
if ((r = sshkey_in_file(key->cert->signature_key,
|
||||
options.trusted_user_ca_keys, 1, 0)) != 0) {
|
||||
debug2("%s: CA %s %s is not listed in %s: %s", __func__,
|
||||
sshkey_type(key->cert->signature_key), ca_fp,
|
||||
options.trusted_user_ca_keys, ssh_err(r));
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
@ -918,7 +621,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
|
||||
auth_debug_add("%s", reason);
|
||||
goto out;
|
||||
}
|
||||
if (key_cert_check_authority(key, 0, 1,
|
||||
if (sshkey_cert_check_authority(key, 0, 1,
|
||||
use_authorized_principals ? NULL : pw->pw_name, &reason) != 0)
|
||||
goto fail_reason;
|
||||
if (auth_cert_options(key, pw, &reason) != 0)
|
||||
@ -927,7 +630,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
|
||||
verbose("Accepted certificate ID \"%s\" (serial %llu) signed by "
|
||||
"%s CA %s via %s", key->cert->key_id,
|
||||
(unsigned long long)key->cert->serial,
|
||||
key_type(key->cert->signature_key), ca_fp,
|
||||
sshkey_type(key->cert->signature_key), ca_fp,
|
||||
options.trusted_user_ca_keys);
|
||||
ret = 1;
|
||||
|
||||
@ -942,7 +645,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
|
||||
* returns 1 if the key is allowed or 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
||||
user_key_allowed2(struct passwd *pw, struct sshkey *key, char *file)
|
||||
{
|
||||
FILE *f;
|
||||
int found_key = 0;
|
||||
@ -965,7 +668,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
||||
* returns 1 if the key is allowed or 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
user_key_command_allowed2(struct passwd *user_pw, Key *key)
|
||||
user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
int r, ok, found_key = 0;
|
||||
@ -1011,7 +714,7 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
|
||||
}
|
||||
|
||||
/* Turn the command into an argument vector */
|
||||
if (split_argv(options.authorized_keys_command, &ac, &av) != 0) {
|
||||
if (argv_split(options.authorized_keys_command, &ac, &av) != 0) {
|
||||
error("AuthorizedKeysCommand \"%s\" contains invalid quotes",
|
||||
command);
|
||||
goto out;
|
||||
@ -1035,7 +738,7 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
|
||||
av[i] = tmp;
|
||||
}
|
||||
/* Prepare a printable command for logs, etc. */
|
||||
command = assemble_argv(ac, av);
|
||||
command = argv_assemble(ac, av);
|
||||
|
||||
/*
|
||||
* If AuthorizedKeysCommand was run without arguments
|
||||
@ -1052,7 +755,8 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
|
||||
}
|
||||
|
||||
if ((pid = subprocess("AuthorizedKeysCommand", pw, command,
|
||||
ac, av, &f)) == 0)
|
||||
ac, av, &f,
|
||||
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
|
||||
goto out;
|
||||
|
||||
uid_swapped = 1;
|
||||
@ -1063,7 +767,7 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
|
||||
if (exited_cleanly(pid, "AuthorizedKeysCommand", command) != 0)
|
||||
if (exited_cleanly(pid, "AuthorizedKeysCommand", command, 0) != 0)
|
||||
goto out;
|
||||
|
||||
/* Read completed successfully */
|
||||
@ -1088,14 +792,15 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
|
||||
* Check whether key authenticates and authorises the user.
|
||||
*/
|
||||
int
|
||||
user_key_allowed(struct passwd *pw, Key *key, int auth_attempt)
|
||||
user_key_allowed(struct passwd *pw, struct sshkey *key, int auth_attempt)
|
||||
{
|
||||
u_int success, i;
|
||||
char *file;
|
||||
|
||||
if (auth_key_is_revoked(key))
|
||||
return 0;
|
||||
if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
|
||||
if (sshkey_is_cert(key) &&
|
||||
auth_key_is_revoked(key->cert->signature_key))
|
||||
return 0;
|
||||
|
||||
success = user_cert_trusted_ca(pw, key);
|
||||
@ -1120,35 +825,6 @@ user_key_allowed(struct passwd *pw, Key *key, int auth_attempt)
|
||||
return success;
|
||||
}
|
||||
|
||||
/* Records a public key in the list of previously-successful keys */
|
||||
void
|
||||
auth2_record_userkey(Authctxt *authctxt, struct sshkey *key)
|
||||
{
|
||||
struct sshkey **tmp;
|
||||
|
||||
if (authctxt->nprev_userkeys >= INT_MAX ||
|
||||
(tmp = reallocarray(authctxt->prev_userkeys,
|
||||
authctxt->nprev_userkeys + 1, sizeof(*tmp))) == NULL)
|
||||
fatal("%s: reallocarray failed", __func__);
|
||||
authctxt->prev_userkeys = tmp;
|
||||
authctxt->prev_userkeys[authctxt->nprev_userkeys] = key;
|
||||
authctxt->nprev_userkeys++;
|
||||
}
|
||||
|
||||
/* Checks whether a key has already been used successfully for authentication */
|
||||
int
|
||||
auth2_userkey_already_used(Authctxt *authctxt, struct sshkey *key)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < authctxt->nprev_userkeys; i++) {
|
||||
if (sshkey_equal_public(key, authctxt->prev_userkeys[i])) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Authmethod method_pubkey = {
|
||||
"publickey",
|
||||
userauth_pubkey,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2.c,v 1.137 2017/02/03 23:05:57 djm Exp $ */
|
||||
/* $OpenBSD: auth2.c,v 1.143 2017/06/24 06:34:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -31,6 +31,7 @@ __RCSID("$FreeBSD$");
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
@ -57,6 +58,7 @@ __RCSID("$FreeBSD$");
|
||||
#include "ssh-gss.h"
|
||||
#endif
|
||||
#include "monitor_wrap.h"
|
||||
#include "ssherr.h"
|
||||
|
||||
/* import */
|
||||
extern ServerOptions options;
|
||||
@ -89,8 +91,8 @@ Authmethod *authmethods[] = {
|
||||
|
||||
/* protocol */
|
||||
|
||||
static int input_service_request(int, u_int32_t, void *);
|
||||
static int input_userauth_request(int, u_int32_t, void *);
|
||||
static int input_service_request(int, u_int32_t, struct ssh *);
|
||||
static int input_userauth_request(int, u_int32_t, struct ssh *);
|
||||
|
||||
/* helper */
|
||||
static Authmethod *authmethod_lookup(Authctxt *, const char *);
|
||||
@ -170,16 +172,19 @@ userauth_banner(void)
|
||||
void
|
||||
do_authentication2(Authctxt *authctxt)
|
||||
{
|
||||
dispatch_init(&dispatch_protocol_error);
|
||||
dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
|
||||
dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
ssh->authctxt = authctxt; /* XXX move to caller */
|
||||
ssh_dispatch_init(ssh, &dispatch_protocol_error);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request);
|
||||
ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success);
|
||||
ssh->authctxt = NULL;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
input_service_request(int type, u_int32_t seq, void *ctxt)
|
||||
input_service_request(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
Authctxt *authctxt = ctxt;
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
u_int len;
|
||||
int acceptit = 0;
|
||||
char *service = packet_get_cstring(&len);
|
||||
@ -192,7 +197,7 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
|
||||
if (!authctxt->success) {
|
||||
acceptit = 1;
|
||||
/* now we can handle user-auth requests */
|
||||
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
|
||||
}
|
||||
}
|
||||
/* XXX all other service requests are denied */
|
||||
@ -212,10 +217,9 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
input_userauth_request(int type, u_int32_t seq, void *ctxt)
|
||||
input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
Authctxt *authctxt = ctxt;
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
Authmethod *m = NULL;
|
||||
char *user, *service, *method, *style = NULL;
|
||||
int authenticated = 0;
|
||||
@ -295,14 +299,15 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
|
||||
#endif /* HAVE_LOGIN_CAP */
|
||||
|
||||
/* reset state */
|
||||
auth2_challenge_stop(authctxt);
|
||||
auth2_challenge_stop(ssh);
|
||||
|
||||
#ifdef GSSAPI
|
||||
/* XXX move to auth2_gssapi_stop() */
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
|
||||
#endif
|
||||
|
||||
auth2_authctxt_reset_info(authctxt);
|
||||
authctxt->postponed = 0;
|
||||
authctxt->server_caused_failure = 0;
|
||||
|
||||
@ -310,9 +315,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
|
||||
m = authmethod_lookup(authctxt, method);
|
||||
if (m != NULL && authctxt->failures < options.max_authtries) {
|
||||
debug2("input_userauth_request: try method %s", method);
|
||||
authenticated = m->userauth(authctxt);
|
||||
authenticated = m->userauth(ssh);
|
||||
}
|
||||
userauth_finish(authctxt, authenticated, method, NULL);
|
||||
userauth_finish(ssh, authenticated, method, NULL);
|
||||
|
||||
free(service);
|
||||
free(user);
|
||||
@ -321,10 +326,10 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
|
||||
}
|
||||
|
||||
void
|
||||
userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
|
||||
userauth_finish(struct ssh *ssh, int authenticated, const char *method,
|
||||
const char *submethod)
|
||||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
Authctxt *authctxt = ssh->authctxt;
|
||||
char *methods;
|
||||
int partial = 0;
|
||||
|
||||
@ -353,6 +358,10 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
|
||||
/* Log before sending the reply */
|
||||
auth_log(authctxt, authenticated, partial, method, submethod);
|
||||
|
||||
/* Update information exposed to session */
|
||||
if (authenticated || partial)
|
||||
auth2_update_session_info(authctxt, method, submethod);
|
||||
|
||||
if (authctxt->postponed)
|
||||
return;
|
||||
|
||||
@ -380,7 +389,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
|
||||
|
||||
if (authenticated == 1) {
|
||||
/* turn off userauth */
|
||||
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
|
||||
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
|
||||
packet_start(SSH2_MSG_USERAUTH_SUCCESS);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
@ -652,4 +661,128 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reset method-specific information */
|
||||
void auth2_authctxt_reset_info(Authctxt *authctxt)
|
||||
{
|
||||
sshkey_free(authctxt->auth_method_key);
|
||||
free(authctxt->auth_method_info);
|
||||
authctxt->auth_method_key = NULL;
|
||||
authctxt->auth_method_info = NULL;
|
||||
}
|
||||
|
||||
/* Record auth method-specific information for logs */
|
||||
void
|
||||
auth2_record_info(Authctxt *authctxt, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
|
||||
free(authctxt->auth_method_info);
|
||||
authctxt->auth_method_info = NULL;
|
||||
|
||||
va_start(ap, fmt);
|
||||
i = vasprintf(&authctxt->auth_method_info, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (i < 0 || authctxt->auth_method_info == NULL)
|
||||
fatal("%s: vasprintf failed", __func__);
|
||||
}
|
||||
|
||||
/*
|
||||
* Records a public key used in authentication. This is used for logging
|
||||
* and to ensure that the same key is not subsequently accepted again for
|
||||
* multiple authentication.
|
||||
*/
|
||||
void
|
||||
auth2_record_key(Authctxt *authctxt, int authenticated,
|
||||
const struct sshkey *key)
|
||||
{
|
||||
struct sshkey **tmp, *dup;
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_demote(key, &dup)) != 0)
|
||||
fatal("%s: copy key: %s", __func__, ssh_err(r));
|
||||
sshkey_free(authctxt->auth_method_key);
|
||||
authctxt->auth_method_key = dup;
|
||||
|
||||
if (!authenticated)
|
||||
return;
|
||||
|
||||
/* If authenticated, make sure we don't accept this key again */
|
||||
if ((r = sshkey_demote(key, &dup)) != 0)
|
||||
fatal("%s: copy key: %s", __func__, ssh_err(r));
|
||||
if (authctxt->nprev_keys >= INT_MAX ||
|
||||
(tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys,
|
||||
authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL)
|
||||
fatal("%s: reallocarray failed", __func__);
|
||||
authctxt->prev_keys = tmp;
|
||||
authctxt->prev_keys[authctxt->nprev_keys] = dup;
|
||||
authctxt->nprev_keys++;
|
||||
|
||||
}
|
||||
|
||||
/* Checks whether a key has already been previously used for authentication */
|
||||
int
|
||||
auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key)
|
||||
{
|
||||
u_int i;
|
||||
char *fp;
|
||||
|
||||
for (i = 0; i < authctxt->nprev_keys; i++) {
|
||||
if (sshkey_equal_public(key, authctxt->prev_keys[i])) {
|
||||
fp = sshkey_fingerprint(authctxt->prev_keys[i],
|
||||
options.fingerprint_hash, SSH_FP_DEFAULT);
|
||||
debug3("%s: key already used: %s %s", __func__,
|
||||
sshkey_type(authctxt->prev_keys[i]),
|
||||
fp == NULL ? "UNKNOWN" : fp);
|
||||
free(fp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates authctxt->session_info with details of authentication. Should be
|
||||
* whenever an authentication method succeeds.
|
||||
*/
|
||||
void
|
||||
auth2_update_session_info(Authctxt *authctxt, const char *method,
|
||||
const char *submethod)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (authctxt->session_info == NULL) {
|
||||
if ((authctxt->session_info = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new", __func__);
|
||||
}
|
||||
|
||||
/* Append method[/submethod] */
|
||||
if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s",
|
||||
method, submethod == NULL ? "" : "/",
|
||||
submethod == NULL ? "" : submethod)) != 0)
|
||||
fatal("%s: append method: %s", __func__, ssh_err(r));
|
||||
|
||||
/* Append key if present */
|
||||
if (authctxt->auth_method_key != NULL) {
|
||||
if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
|
||||
(r = sshkey_format_text(authctxt->auth_method_key,
|
||||
authctxt->session_info)) != 0)
|
||||
fatal("%s: append key: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
if (authctxt->auth_method_info != NULL) {
|
||||
/* Ensure no ambiguity here */
|
||||
if (strchr(authctxt->auth_method_info, '\n') != NULL)
|
||||
fatal("%s: auth_method_info contains \\n", __func__);
|
||||
if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
|
||||
(r = sshbuf_putf(authctxt->session_info, "%s",
|
||||
authctxt->auth_method_info)) != 0) {
|
||||
fatal("%s: append method info: %s",
|
||||
__func__, ssh_err(r));
|
||||
}
|
||||
}
|
||||
if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0)
|
||||
fatal("%s: append: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: authfd.c,v 1.100 2015/12/04 16:41:28 markus Exp $ */
|
||||
/* $OpenBSD: authfd.c,v 1.105 2017/07/01 13:50:45 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -51,7 +51,6 @@
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
#include "rsa.h"
|
||||
#include "sshbuf.h"
|
||||
#include "sshkey.h"
|
||||
#include "authfd.h"
|
||||
@ -199,43 +198,6 @@ ssh_lock_agent(int sock, int lock, const char *password)
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
static int
|
||||
deserialise_identity1(struct sshbuf *ids, struct sshkey **keyp, char **commentp)
|
||||
{
|
||||
struct sshkey *key;
|
||||
int r, keybits;
|
||||
u_int32_t bits;
|
||||
char *comment = NULL;
|
||||
|
||||
if ((key = sshkey_new(KEY_RSA1)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if ((r = sshbuf_get_u32(ids, &bits)) != 0 ||
|
||||
(r = sshbuf_get_bignum1(ids, key->rsa->e)) != 0 ||
|
||||
(r = sshbuf_get_bignum1(ids, key->rsa->n)) != 0 ||
|
||||
(r = sshbuf_get_cstring(ids, &comment, NULL)) != 0)
|
||||
goto out;
|
||||
keybits = BN_num_bits(key->rsa->n);
|
||||
/* XXX previously we just warned here. I think we should be strict */
|
||||
if (keybits < 0 || bits != (u_int)keybits) {
|
||||
r = SSH_ERR_KEY_BITS_MISMATCH;
|
||||
goto out;
|
||||
}
|
||||
if (keyp != NULL) {
|
||||
*keyp = key;
|
||||
key = NULL;
|
||||
}
|
||||
if (commentp != NULL) {
|
||||
*commentp = comment;
|
||||
comment = NULL;
|
||||
}
|
||||
r = 0;
|
||||
out:
|
||||
sshkey_free(key);
|
||||
free(comment);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp)
|
||||
@ -264,35 +226,21 @@ deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp)
|
||||
* Fetch list of identities held by the agent.
|
||||
*/
|
||||
int
|
||||
ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp)
|
||||
ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp)
|
||||
{
|
||||
u_char type, code1 = 0, code2 = 0;
|
||||
u_char type;
|
||||
u_int32_t num, i;
|
||||
struct sshbuf *msg;
|
||||
struct ssh_identitylist *idl = NULL;
|
||||
int r;
|
||||
|
||||
/* Determine request and expected response types */
|
||||
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 SSH_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a message to the agent requesting for a list of the
|
||||
* identities it can represent.
|
||||
*/
|
||||
if ((msg = sshbuf_new()) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if ((r = sshbuf_put_u8(msg, code1)) != 0)
|
||||
if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_REQUEST_IDENTITIES)) != 0)
|
||||
goto out;
|
||||
|
||||
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
|
||||
@ -304,7 +252,7 @@ ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp)
|
||||
if (agent_failed(type)) {
|
||||
r = SSH_ERR_AGENT_FAILURE;
|
||||
goto out;
|
||||
} else if (type != code2) {
|
||||
} else if (type != SSH2_AGENT_IDENTITIES_ANSWER) {
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
@ -329,17 +277,8 @@ ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp)
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < num;) {
|
||||
switch (version) {
|
||||
case 1:
|
||||
#ifdef WITH_SSH1
|
||||
if ((r = deserialise_identity1(msg,
|
||||
&(idl->keys[i]), &(idl->comments[i]))) != 0)
|
||||
goto out;
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
if ((r = deserialise_identity2(msg,
|
||||
&(idl->keys[i]), &(idl->comments[i]))) != 0) {
|
||||
if ((r = deserialise_identity2(msg, &(idl->keys[i]),
|
||||
&(idl->comments[i]))) != 0) {
|
||||
if (r == SSH_ERR_KEY_TYPE_UNKNOWN) {
|
||||
/* Gracefully skip unknown key types */
|
||||
num--;
|
||||
@ -347,8 +286,6 @@ ssh_fetch_identitylist(int sock, int version, struct ssh_identitylist **idlp)
|
||||
} else
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
idl->nkeys = num;
|
||||
@ -385,50 +322,10 @@ ssh_free_identitylist(struct ssh_identitylist *idl)
|
||||
* otherwise.
|
||||
*/
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
int
|
||||
ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
|
||||
u_char session_id[16], u_char response[16])
|
||||
{
|
||||
struct sshbuf *msg;
|
||||
int r;
|
||||
u_char type;
|
||||
|
||||
if (key->type != KEY_RSA1)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if ((msg = sshbuf_new()) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if ((r = sshbuf_put_u8(msg, SSH_AGENTC_RSA_CHALLENGE)) != 0 ||
|
||||
(r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 ||
|
||||
(r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 ||
|
||||
(r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0 ||
|
||||
(r = sshbuf_put_bignum1(msg, challenge)) != 0 ||
|
||||
(r = sshbuf_put(msg, session_id, 16)) != 0 ||
|
||||
(r = sshbuf_put_u32(msg, 1)) != 0) /* Response type for proto 1.1 */
|
||||
goto out;
|
||||
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
|
||||
goto out;
|
||||
if ((r = sshbuf_get_u8(msg, &type)) != 0)
|
||||
goto out;
|
||||
if (agent_failed(type)) {
|
||||
r = SSH_ERR_AGENT_FAILURE;
|
||||
goto out;
|
||||
} else if (type != SSH_AGENT_RSA_RESPONSE) {
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshbuf_get(msg, response, 16)) != 0)
|
||||
goto out;
|
||||
r = 0;
|
||||
out:
|
||||
sshbuf_free(msg);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* encode signature algoritm in flag bits, so we can keep the msg format */
|
||||
static u_int
|
||||
agent_encode_alg(struct sshkey *key, const char *alg)
|
||||
agent_encode_alg(const struct sshkey *key, const char *alg)
|
||||
{
|
||||
if (alg != NULL && key->type == KEY_RSA) {
|
||||
if (strcmp(alg, "rsa-sha2-256") == 0)
|
||||
@ -441,7 +338,7 @@ agent_encode_alg(struct sshkey *key, const char *alg)
|
||||
|
||||
/* ask agent to sign data, returns err.h code on error, 0 on success */
|
||||
int
|
||||
ssh_agent_sign(int sock, struct sshkey *key,
|
||||
ssh_agent_sign(int sock, const struct sshkey *key,
|
||||
u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, const char *alg, u_int compat)
|
||||
{
|
||||
@ -494,25 +391,6 @@ ssh_agent_sign(int sock, struct sshkey *key,
|
||||
|
||||
/* Encode key for a message to the agent. */
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
static int
|
||||
ssh_encode_identity_rsa1(struct sshbuf *b, RSA *key, const char *comment)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* To keep within the protocol: p < q for ssh. in SSL p > q */
|
||||
if ((r = sshbuf_put_u32(b, BN_num_bits(key->n))) != 0 ||
|
||||
(r = sshbuf_put_bignum1(b, key->n)) != 0 ||
|
||||
(r = sshbuf_put_bignum1(b, key->e)) != 0 ||
|
||||
(r = sshbuf_put_bignum1(b, key->d)) != 0 ||
|
||||
(r = sshbuf_put_bignum1(b, key->iqmp)) != 0 ||
|
||||
(r = sshbuf_put_bignum1(b, key->q)) != 0 ||
|
||||
(r = sshbuf_put_bignum1(b, key->p)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, comment)) != 0)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ssh_encode_identity_ssh2(struct sshbuf *b, struct sshkey *key,
|
||||
@ -561,16 +439,6 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment,
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
|
||||
switch (key->type) {
|
||||
#ifdef WITH_SSH1
|
||||
case KEY_RSA1:
|
||||
type = constrained ?
|
||||
SSH_AGENTC_ADD_RSA_ID_CONSTRAINED :
|
||||
SSH_AGENTC_ADD_RSA_IDENTITY;
|
||||
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
|
||||
(r = ssh_encode_identity_rsa1(msg, key->rsa, comment)) != 0)
|
||||
goto out;
|
||||
break;
|
||||
#endif
|
||||
#ifdef WITH_OPENSSL
|
||||
case KEY_RSA:
|
||||
case KEY_RSA_CERT:
|
||||
@ -620,16 +488,6 @@ ssh_remove_identity(int sock, struct sshkey *key)
|
||||
if ((msg = sshbuf_new()) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
if (key->type == KEY_RSA1) {
|
||||
if ((r = sshbuf_put_u8(msg,
|
||||
SSH_AGENTC_REMOVE_RSA_IDENTITY)) != 0 ||
|
||||
(r = sshbuf_put_u32(msg, BN_num_bits(key->rsa->n))) != 0 ||
|
||||
(r = sshbuf_put_bignum1(msg, key->rsa->e)) != 0 ||
|
||||
(r = sshbuf_put_bignum1(msg, key->rsa->n)) != 0)
|
||||
goto out;
|
||||
} else
|
||||
#endif
|
||||
if (key->type != KEY_UNSPEC) {
|
||||
if ((r = sshkey_to_blob(key, &blob, &blen)) != 0)
|
||||
goto out;
|
||||
@ -696,6 +554,10 @@ ssh_update_card(int sock, int add, const char *reader_id, const char *pin,
|
||||
/*
|
||||
* Removes all identities from the agent.
|
||||
* This call is intended only for use by ssh-add(1) and like applications.
|
||||
*
|
||||
* This supports the SSH protocol 1 message to because, when clearing all
|
||||
* keys from an agent, we generally want to clear both protocol v1 and v2
|
||||
* keys.
|
||||
*/
|
||||
int
|
||||
ssh_remove_all_identities(int sock, int version)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: authfd.h,v 1.39 2015/12/04 16:41:28 markus Exp $ */
|
||||
/* $OpenBSD: authfd.h,v 1.41 2017/06/28 01:09:22 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -27,8 +27,7 @@ int ssh_get_authentication_socket(int *fdp);
|
||||
void ssh_close_authentication_socket(int sock);
|
||||
|
||||
int ssh_lock_agent(int sock, int lock, const char *password);
|
||||
int ssh_fetch_identitylist(int sock, int version,
|
||||
struct ssh_identitylist **idlp);
|
||||
int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp);
|
||||
void ssh_free_identitylist(struct ssh_identitylist *idl);
|
||||
int ssh_add_identity_constrained(int sock, struct sshkey *key,
|
||||
const char *comment, u_int life, u_int confirm);
|
||||
@ -39,7 +38,7 @@ int ssh_remove_all_identities(int sock, int version);
|
||||
|
||||
int ssh_decrypt_challenge(int sock, struct sshkey* key, BIGNUM *challenge,
|
||||
u_char session_id[16], u_char response[16]);
|
||||
int ssh_agent_sign(int sock, struct sshkey *key,
|
||||
int ssh_agent_sign(int sock, const struct sshkey *key,
|
||||
u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, const char *alg, u_int compat);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: authfile.c,v 1.122 2016/11/25 23:24:45 djm Exp $ */
|
||||
/* $OpenBSD: authfile.c,v 1.127 2017/07/01 13:50:45 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -42,7 +42,6 @@
|
||||
#include "ssh.h"
|
||||
#include "log.h"
|
||||
#include "authfile.h"
|
||||
#include "rsa.h"
|
||||
#include "misc.h"
|
||||
#include "atomicio.h"
|
||||
#include "sshkey.h"
|
||||
@ -100,25 +99,13 @@ sshkey_load_file(int fd, struct sshbuf *blob)
|
||||
u_char buf[1024];
|
||||
size_t len;
|
||||
struct stat st;
|
||||
int r, dontmax = 0;
|
||||
int r;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return SSH_ERR_SYSTEM_ERROR;
|
||||
if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
|
||||
st.st_size > MAX_KEY_FILE_SIZE)
|
||||
return SSH_ERR_INVALID_FORMAT;
|
||||
/*
|
||||
* Pre-allocate the buffer used for the key contents and clamp its
|
||||
* maximum size. This ensures that key contents are never leaked via
|
||||
* implicit realloc() in the sshbuf code.
|
||||
*/
|
||||
if ((st.st_mode & S_IFREG) == 0 || st.st_size <= 0) {
|
||||
st.st_size = 64*1024; /* 64k should be enough for anyone :) */
|
||||
dontmax = 1;
|
||||
}
|
||||
if ((r = sshbuf_allocate(blob, st.st_size)) != 0 ||
|
||||
(dontmax && (r = sshbuf_set_max_size(blob, st.st_size)) != 0))
|
||||
return r;
|
||||
for (;;) {
|
||||
if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
|
||||
if (errno == EPIPE)
|
||||
@ -147,35 +134,6 @@ sshkey_load_file(int fd, struct sshbuf *blob)
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
/*
|
||||
* Loads the public part of the ssh v1 key file. Returns NULL if an error was
|
||||
* encountered (the file does not exist or is not readable), and the key
|
||||
* otherwise.
|
||||
*/
|
||||
static int
|
||||
sshkey_load_public_rsa1(int fd, struct sshkey **keyp, char **commentp)
|
||||
{
|
||||
struct sshbuf *b = NULL;
|
||||
int r;
|
||||
|
||||
if (keyp != NULL)
|
||||
*keyp = NULL;
|
||||
if (commentp != NULL)
|
||||
*commentp = NULL;
|
||||
|
||||
if ((b = sshbuf_new()) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if ((r = sshkey_load_file(fd, b)) != 0)
|
||||
goto out;
|
||||
if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0)
|
||||
goto out;
|
||||
r = 0;
|
||||
out:
|
||||
sshbuf_free(b);
|
||||
return r;
|
||||
}
|
||||
#endif /* WITH_SSH1 */
|
||||
|
||||
/* XXX remove error() calls from here? */
|
||||
int
|
||||
@ -345,75 +303,48 @@ sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp)
|
||||
return SSH_ERR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
/* load public key from ssh v1 private or any pubkey file */
|
||||
/* load public key from any pubkey file */
|
||||
int
|
||||
sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
|
||||
{
|
||||
struct sshkey *pub = NULL;
|
||||
char file[PATH_MAX];
|
||||
int r, fd;
|
||||
char *file = NULL;
|
||||
int r;
|
||||
|
||||
if (keyp != NULL)
|
||||
*keyp = NULL;
|
||||
if (commentp != NULL)
|
||||
*commentp = NULL;
|
||||
|
||||
/* XXX should load file once and attempt to parse each format */
|
||||
|
||||
if ((fd = open(filename, O_RDONLY)) < 0)
|
||||
goto skip;
|
||||
#ifdef WITH_SSH1
|
||||
/* try rsa1 private key */
|
||||
r = sshkey_load_public_rsa1(fd, keyp, commentp);
|
||||
close(fd);
|
||||
switch (r) {
|
||||
case SSH_ERR_INTERNAL_ERROR:
|
||||
case SSH_ERR_ALLOC_FAIL:
|
||||
case SSH_ERR_INVALID_ARGUMENT:
|
||||
case SSH_ERR_SYSTEM_ERROR:
|
||||
case 0:
|
||||
return r;
|
||||
}
|
||||
#else /* WITH_SSH1 */
|
||||
close(fd);
|
||||
#endif /* WITH_SSH1 */
|
||||
|
||||
/* try ssh2 public key */
|
||||
if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
|
||||
if (keyp != NULL)
|
||||
if (keyp != NULL) {
|
||||
*keyp = pub;
|
||||
return 0;
|
||||
pub = NULL;
|
||||
}
|
||||
r = 0;
|
||||
goto out;
|
||||
}
|
||||
sshkey_free(pub);
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
/* try rsa1 public key */
|
||||
if ((pub = sshkey_new(KEY_RSA1)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
|
||||
if (keyp != NULL)
|
||||
*keyp = pub;
|
||||
return 0;
|
||||
}
|
||||
sshkey_free(pub);
|
||||
#endif /* WITH_SSH1 */
|
||||
|
||||
skip:
|
||||
/* try .pub suffix */
|
||||
if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
|
||||
if (asprintf(&file, "%s.pub", filename) == -1)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */
|
||||
if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
|
||||
(strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
|
||||
(r = sshkey_try_load_public(pub, file, commentp)) == 0) {
|
||||
if (keyp != NULL)
|
||||
*keyp = pub;
|
||||
return 0;
|
||||
if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshkey_try_load_public(pub, file, commentp)) == 0) {
|
||||
if (keyp != NULL) {
|
||||
*keyp = pub;
|
||||
pub = NULL;
|
||||
}
|
||||
r = 0;
|
||||
}
|
||||
out:
|
||||
free(file);
|
||||
sshkey_free(pub);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,9 @@ void
|
||||
bitmap_free(struct bitmap *b)
|
||||
{
|
||||
if (b != NULL && b->d != NULL) {
|
||||
explicit_bzero(b->d, b->len);
|
||||
bitmap_zero(b);
|
||||
free(b->d);
|
||||
b->d = NULL;
|
||||
}
|
||||
free(b);
|
||||
}
|
||||
@ -86,10 +87,10 @@ reserve(struct bitmap *b, u_int n)
|
||||
return -1; /* invalid */
|
||||
nlen = (n / BITMAP_BITS) + 1;
|
||||
if (b->len < nlen) {
|
||||
if ((tmp = reallocarray(b->d, nlen, BITMAP_BYTES)) == NULL)
|
||||
if ((tmp = recallocarray(b->d, b->len,
|
||||
nlen, BITMAP_BYTES)) == NULL)
|
||||
return -1;
|
||||
b->d = tmp;
|
||||
memset(b->d + b->len, 0, (nlen - b->len) * BITMAP_BYTES);
|
||||
b->len = nlen;
|
||||
}
|
||||
return 0;
|
||||
@ -188,7 +189,7 @@ bitmap_from_string(struct bitmap *b, const void *p, size_t l)
|
||||
{
|
||||
int r;
|
||||
size_t i, offset, shift;
|
||||
u_char *s = (u_char *)p;
|
||||
const u_char *s = (const u_char *)p;
|
||||
|
||||
if (l > BITMAP_MAX / 8)
|
||||
return -1;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: bufbn.c,v 1.12 2014/04/30 05:29:56 djm Exp $ */
|
||||
/* $OpenBSD: bufbn.c,v 1.13 2017/04/30 23:23:54 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
|
||||
@ -28,46 +28,6 @@
|
||||
#include "log.h"
|
||||
#include "ssherr.h"
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
int
|
||||
buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = sshbuf_put_bignum1(buffer, value)) != 0) {
|
||||
error("%s: %s", __func__, ssh_err(ret));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
buffer_put_bignum(Buffer *buffer, const BIGNUM *value)
|
||||
{
|
||||
if (buffer_put_bignum_ret(buffer, value) == -1)
|
||||
fatal("%s: buffer error", __func__);
|
||||
}
|
||||
|
||||
int
|
||||
buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = sshbuf_get_bignum1(buffer, value)) != 0) {
|
||||
error("%s: %s", __func__, ssh_err(ret));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
buffer_get_bignum(Buffer *buffer, BIGNUM *value)
|
||||
{
|
||||
if (buffer_get_bignum_ret(buffer, value) == -1)
|
||||
fatal("%s: buffer error", __func__);
|
||||
}
|
||||
#endif /* WITH_SSH1 */
|
||||
|
||||
int
|
||||
buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: buffer.h,v 1.25 2014/04/30 05:29:56 djm Exp $ */
|
||||
/* $OpenBSD: buffer.h,v 1.26 2017/04/30 23:23:54 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 Damien Miller <djm@mindrot.org>
|
||||
@ -49,9 +49,7 @@ int buffer_consume_end_ret(Buffer *, u_int);
|
||||
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/bn.h>
|
||||
void buffer_put_bignum(Buffer *, const BIGNUM *);
|
||||
void buffer_put_bignum2(Buffer *, const BIGNUM *);
|
||||
void buffer_get_bignum(Buffer *, BIGNUM *);
|
||||
void buffer_get_bignum2(Buffer *, BIGNUM *);
|
||||
void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int);
|
||||
|
||||
@ -75,8 +73,6 @@ void buffer_put_cstring(Buffer *, const char *);
|
||||
|
||||
#define buffer_skip_string(b) (void)buffer_get_string_ptr(b, NULL);
|
||||
|
||||
int buffer_put_bignum_ret(Buffer *, const BIGNUM *);
|
||||
int buffer_get_bignum_ret(Buffer *, BIGNUM *);
|
||||
int buffer_put_bignum2_ret(Buffer *, const BIGNUM *);
|
||||
int buffer_get_bignum2_ret(Buffer *, BIGNUM *);
|
||||
int buffer_get_short_ret(u_short *, Buffer *);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: channels.h,v 1.121 2017/02/01 02:59:09 dtucker Exp $ */
|
||||
/* $OpenBSD: channels.h,v 1.130 2017/09/21 19:16:53 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -46,8 +46,6 @@
|
||||
#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_RPORT_LISTENER 11 /* Listening to a R-style port */
|
||||
#define SSH_CHANNEL_CONNECTING 12
|
||||
@ -59,22 +57,27 @@
|
||||
#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */
|
||||
#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */
|
||||
#define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-slave */
|
||||
#define SSH_CHANNEL_MAX_TYPE 21
|
||||
#define SSH_CHANNEL_RDYNAMIC_OPEN 21 /* reverse SOCKS, parsing request */
|
||||
#define SSH_CHANNEL_RDYNAMIC_FINISH 22 /* reverse SOCKS, finishing connect */
|
||||
#define SSH_CHANNEL_MAX_TYPE 23
|
||||
|
||||
#define CHANNEL_CANCEL_PORT_STATIC -1
|
||||
|
||||
struct ssh;
|
||||
struct Channel;
|
||||
typedef struct Channel Channel;
|
||||
struct fwd_perm_list;
|
||||
|
||||
typedef void channel_open_fn(int, int, void *);
|
||||
typedef void channel_callback_fn(int, void *);
|
||||
typedef int channel_infilter_fn(struct Channel *, char *, int);
|
||||
typedef void channel_filter_cleanup_fn(int, void *);
|
||||
typedef u_char *channel_outfilter_fn(struct Channel *, u_char **, u_int *);
|
||||
typedef void channel_open_fn(struct ssh *, int, int, void *);
|
||||
typedef void channel_callback_fn(struct ssh *, int, void *);
|
||||
typedef int channel_infilter_fn(struct ssh *, struct Channel *, char *, int);
|
||||
typedef void channel_filter_cleanup_fn(struct ssh *, int, void *);
|
||||
typedef u_char *channel_outfilter_fn(struct ssh *, struct Channel *,
|
||||
u_char **, size_t *);
|
||||
|
||||
/* Channel success/failure callbacks */
|
||||
typedef void channel_confirm_cb(int, struct Channel *, void *);
|
||||
typedef void channel_confirm_abandon_cb(struct Channel *, void *);
|
||||
typedef void channel_confirm_cb(struct ssh *, int, struct Channel *, void *);
|
||||
typedef void channel_confirm_abandon_cb(struct ssh *, struct Channel *, void *);
|
||||
struct channel_confirm {
|
||||
TAILQ_ENTRY(channel_confirm) entry;
|
||||
channel_confirm_cb *cb;
|
||||
@ -91,12 +94,14 @@ struct channel_connect {
|
||||
};
|
||||
|
||||
/* Callbacks for mux channels back into client-specific code */
|
||||
typedef int mux_callback_fn(struct Channel *);
|
||||
typedef int mux_callback_fn(struct ssh *, struct Channel *);
|
||||
|
||||
struct Channel {
|
||||
int type; /* channel type/state */
|
||||
int self; /* my own channel identifier */
|
||||
int remote_id; /* channel identifier for remote peer */
|
||||
uint32_t remote_id; /* channel identifier for remote peer */
|
||||
int have_remote_id; /* non-zero if remote_id is valid */
|
||||
|
||||
u_int istate; /* input from channel (state of receive half) */
|
||||
u_int ostate; /* output to channel (state of transmit half) */
|
||||
int flags; /* close sent/rcvd */
|
||||
@ -117,11 +122,12 @@ struct Channel {
|
||||
* to a matching pre-select handler.
|
||||
* this way post-select handlers are not
|
||||
* accidentally called if a FD gets reused */
|
||||
Buffer input; /* data read from socket, to be sent over
|
||||
struct sshbuf *input; /* data read from socket, to be sent over
|
||||
* encrypted connection */
|
||||
Buffer output; /* data received over encrypted connection for
|
||||
struct sshbuf *output; /* data received over encrypted connection for
|
||||
* send on socket */
|
||||
Buffer extended;
|
||||
struct sshbuf *extended;
|
||||
|
||||
char *path;
|
||||
/* path for unix domain sockets, or host name for forwards */
|
||||
int listening_port; /* port being listened for forwards */
|
||||
@ -157,6 +163,7 @@ struct Channel {
|
||||
int datagram;
|
||||
|
||||
/* non-blocking connect */
|
||||
/* XXX make this a pointer so the structure can be opaque */
|
||||
struct channel_connect connect_ctx;
|
||||
|
||||
/* multiplexing protocol hook, called for each packet received */
|
||||
@ -196,128 +203,137 @@ struct Channel {
|
||||
#define CHAN_EOF_RCVD 0x08
|
||||
#define CHAN_LOCAL 0x10
|
||||
|
||||
#define CHAN_RBUF 16*1024
|
||||
/* Read buffer size */
|
||||
#define CHAN_RBUF (16*1024)
|
||||
|
||||
/* Hard limit on number of channels */
|
||||
#define CHANNELS_MAX_CHANNELS (16*1024)
|
||||
|
||||
/* check whether 'efd' is still in use */
|
||||
#define CHANNEL_EFD_INPUT_ACTIVE(c) \
|
||||
(compat20 && c->extended_usage == CHAN_EXTENDED_READ && \
|
||||
(c->extended_usage == CHAN_EXTENDED_READ && \
|
||||
(c->efd != -1 || \
|
||||
buffer_len(&c->extended) > 0))
|
||||
sshbuf_len(c->extended) > 0))
|
||||
#define CHANNEL_EFD_OUTPUT_ACTIVE(c) \
|
||||
(compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \
|
||||
(c->extended_usage == CHAN_EXTENDED_WRITE && \
|
||||
c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \
|
||||
buffer_len(&c->extended) > 0))
|
||||
sshbuf_len(c->extended) > 0))
|
||||
|
||||
/* Add channel management structures to SSH transport instance */
|
||||
void channel_init_channels(struct ssh *ssh);
|
||||
|
||||
/* channel management */
|
||||
|
||||
Channel *channel_by_id(int);
|
||||
Channel *channel_by_remote_id(int);
|
||||
Channel *channel_lookup(int);
|
||||
Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int);
|
||||
void channel_set_fds(int, int, int, int, int, int, int, u_int);
|
||||
void channel_free(Channel *);
|
||||
void channel_free_all(void);
|
||||
void channel_stop_listening(void);
|
||||
Channel *channel_by_id(struct ssh *, int);
|
||||
Channel *channel_by_remote_id(struct ssh *, u_int);
|
||||
Channel *channel_lookup(struct ssh *, int);
|
||||
Channel *channel_new(struct ssh *, char *, int, int, int, int,
|
||||
u_int, u_int, int, char *, int);
|
||||
void channel_set_fds(struct ssh *, int, int, int, int, int,
|
||||
int, int, u_int);
|
||||
void channel_free(struct ssh *, Channel *);
|
||||
void channel_free_all(struct ssh *);
|
||||
void channel_stop_listening(struct ssh *);
|
||||
|
||||
void channel_send_open(int);
|
||||
void channel_request_start(int, char *, int);
|
||||
void channel_register_cleanup(int, channel_callback_fn *, int);
|
||||
void channel_register_open_confirm(int, channel_open_fn *, void *);
|
||||
void channel_register_filter(int, channel_infilter_fn *,
|
||||
void channel_send_open(struct ssh *, int);
|
||||
void channel_request_start(struct ssh *, int, char *, int);
|
||||
void channel_register_cleanup(struct ssh *, int,
|
||||
channel_callback_fn *, int);
|
||||
void channel_register_open_confirm(struct ssh *, int,
|
||||
channel_open_fn *, void *);
|
||||
void channel_register_filter(struct ssh *, int, channel_infilter_fn *,
|
||||
channel_outfilter_fn *, channel_filter_cleanup_fn *, void *);
|
||||
void channel_register_status_confirm(int, channel_confirm_cb *,
|
||||
channel_confirm_abandon_cb *, void *);
|
||||
void channel_cancel_cleanup(int);
|
||||
int channel_close_fd(int *);
|
||||
void channel_send_window_changes(void);
|
||||
void channel_register_status_confirm(struct ssh *, int,
|
||||
channel_confirm_cb *, channel_confirm_abandon_cb *, void *);
|
||||
void channel_cancel_cleanup(struct ssh *, int);
|
||||
int channel_close_fd(struct ssh *, int *);
|
||||
void channel_send_window_changes(struct ssh *);
|
||||
|
||||
/* mux proxy support */
|
||||
|
||||
int channel_proxy_downstream(Channel *mc);
|
||||
int channel_proxy_upstream(Channel *, int, u_int32_t, void *);
|
||||
int channel_proxy_downstream(struct ssh *, Channel *mc);
|
||||
int channel_proxy_upstream(Channel *, int, u_int32_t, struct ssh *);
|
||||
|
||||
/* protocol handler */
|
||||
|
||||
int channel_input_close(int, u_int32_t, void *);
|
||||
int channel_input_close_confirmation(int, u_int32_t, void *);
|
||||
int channel_input_data(int, u_int32_t, void *);
|
||||
int channel_input_extended_data(int, u_int32_t, void *);
|
||||
int channel_input_ieof(int, u_int32_t, void *);
|
||||
int channel_input_oclose(int, u_int32_t, void *);
|
||||
int channel_input_open_confirmation(int, u_int32_t, void *);
|
||||
int channel_input_open_failure(int, u_int32_t, void *);
|
||||
int channel_input_port_open(int, u_int32_t, void *);
|
||||
int channel_input_window_adjust(int, u_int32_t, void *);
|
||||
int channel_input_status_confirm(int, u_int32_t, void *);
|
||||
int channel_input_data(int, u_int32_t, struct ssh *);
|
||||
int channel_input_extended_data(int, u_int32_t, struct ssh *);
|
||||
int channel_input_ieof(int, u_int32_t, struct ssh *);
|
||||
int channel_input_oclose(int, u_int32_t, struct ssh *);
|
||||
int channel_input_open_confirmation(int, u_int32_t, struct ssh *);
|
||||
int channel_input_open_failure(int, u_int32_t, struct ssh *);
|
||||
int channel_input_port_open(int, u_int32_t, struct ssh *);
|
||||
int channel_input_window_adjust(int, u_int32_t, struct ssh *);
|
||||
int channel_input_status_confirm(int, u_int32_t, struct ssh *);
|
||||
|
||||
/* file descriptor handling (read/write) */
|
||||
|
||||
void channel_prepare_select(fd_set **, fd_set **, int *, u_int*,
|
||||
time_t*, int);
|
||||
void channel_after_select(fd_set *, fd_set *);
|
||||
void channel_output_poll(void);
|
||||
void channel_prepare_select(struct ssh *, fd_set **, fd_set **, int *,
|
||||
u_int*, time_t*);
|
||||
void channel_after_select(struct ssh *, fd_set *, fd_set *);
|
||||
void channel_output_poll(struct ssh *);
|
||||
|
||||
int channel_not_very_much_buffered_data(void);
|
||||
void channel_close_all(void);
|
||||
int channel_still_open(void);
|
||||
char *channel_open_message(void);
|
||||
int channel_find_open(void);
|
||||
int channel_not_very_much_buffered_data(struct ssh *);
|
||||
void channel_close_all(struct ssh *);
|
||||
int channel_still_open(struct ssh *);
|
||||
char *channel_open_message(struct ssh *);
|
||||
int channel_find_open(struct ssh *);
|
||||
|
||||
/* tcp forwarding */
|
||||
struct Forward;
|
||||
struct ForwardOptions;
|
||||
void channel_set_af(int af);
|
||||
void channel_permit_all_opens(void);
|
||||
void channel_add_permitted_opens(char *, int);
|
||||
int channel_add_adm_permitted_opens(char *, int);
|
||||
void channel_disable_adm_local_opens(void);
|
||||
void channel_update_permitted_opens(int, int);
|
||||
void channel_clear_permitted_opens(void);
|
||||
void channel_clear_adm_permitted_opens(void);
|
||||
void channel_print_adm_permitted_opens(void);
|
||||
Channel *channel_connect_to_port(const char *, u_short, char *, char *, int *,
|
||||
const char **);
|
||||
Channel *channel_connect_to_path(const char *, char *, char *);
|
||||
Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
|
||||
Channel *channel_connect_by_listen_address(const char *, u_short,
|
||||
void channel_set_af(struct ssh *, int af);
|
||||
void channel_permit_all_opens(struct ssh *);
|
||||
void channel_add_permitted_opens(struct ssh *, char *, int);
|
||||
int channel_add_adm_permitted_opens(struct ssh *, char *, int);
|
||||
void channel_copy_adm_permitted_opens(struct ssh *,
|
||||
const struct fwd_perm_list *);
|
||||
void channel_disable_adm_local_opens(struct ssh *);
|
||||
void channel_update_permitted_opens(struct ssh *, int, int);
|
||||
void channel_clear_permitted_opens(struct ssh *);
|
||||
void channel_clear_adm_permitted_opens(struct ssh *);
|
||||
void channel_print_adm_permitted_opens(struct ssh *);
|
||||
Channel *channel_connect_to_port(struct ssh *, const char *, u_short,
|
||||
char *, char *, int *, const char **);
|
||||
Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *);
|
||||
Channel *channel_connect_stdio_fwd(struct ssh *, const char*,
|
||||
u_short, int, int);
|
||||
Channel *channel_connect_by_listen_address(struct ssh *, const char *,
|
||||
u_short, char *, char *);
|
||||
Channel *channel_connect_by_listen_path(struct ssh *, const char *,
|
||||
char *, char *);
|
||||
Channel *channel_connect_by_listen_path(const char *, char *, char *);
|
||||
int channel_request_remote_forwarding(struct Forward *);
|
||||
int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *);
|
||||
int channel_request_rforward_cancel(struct Forward *);
|
||||
int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *);
|
||||
int channel_cancel_rport_listener(struct Forward *);
|
||||
int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *);
|
||||
int channel_request_remote_forwarding(struct ssh *, struct Forward *);
|
||||
int channel_setup_local_fwd_listener(struct ssh *, struct Forward *,
|
||||
struct ForwardOptions *);
|
||||
int channel_request_rforward_cancel(struct ssh *, struct Forward *);
|
||||
int channel_setup_remote_fwd_listener(struct ssh *, struct Forward *,
|
||||
int *, struct ForwardOptions *);
|
||||
int channel_cancel_rport_listener(struct ssh *, struct Forward *);
|
||||
int channel_cancel_lport_listener(struct ssh *, struct Forward *,
|
||||
int, struct ForwardOptions *);
|
||||
int permitopen_port(const char *);
|
||||
|
||||
/* x11 forwarding */
|
||||
|
||||
void channel_set_x11_refuse_time(u_int);
|
||||
int x11_connect_display(void);
|
||||
int x11_create_display_inet(int, int, int, u_int *, int **);
|
||||
int x11_input_open(int, u_int32_t, void *);
|
||||
void x11_request_forwarding_with_spoofing(int, const char *, const char *,
|
||||
const char *, int);
|
||||
int deny_input_open(int, u_int32_t, void *);
|
||||
|
||||
/* agent forwarding */
|
||||
|
||||
void auth_request_forwarding(void);
|
||||
void channel_set_x11_refuse_time(struct ssh *, u_int);
|
||||
int x11_connect_display(struct ssh *);
|
||||
int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **);
|
||||
void x11_request_forwarding_with_spoofing(struct ssh *, int,
|
||||
const char *, const char *, const char *, int);
|
||||
|
||||
/* channel close */
|
||||
|
||||
int chan_is_dead(Channel *, int);
|
||||
void chan_mark_dead(Channel *);
|
||||
int chan_is_dead(struct ssh *, Channel *, int);
|
||||
void chan_mark_dead(struct ssh *, Channel *);
|
||||
|
||||
/* channel events */
|
||||
|
||||
void chan_rcvd_oclose(Channel *);
|
||||
void chan_rcvd_eow(Channel *); /* SSH2-only */
|
||||
void chan_read_failed(Channel *);
|
||||
void chan_ibuf_empty(Channel *);
|
||||
|
||||
void chan_rcvd_ieof(Channel *);
|
||||
void chan_write_failed(Channel *);
|
||||
void chan_obuf_empty(Channel *);
|
||||
void chan_rcvd_oclose(struct ssh *, Channel *);
|
||||
void chan_rcvd_eow(struct ssh *, Channel *);
|
||||
void chan_read_failed(struct ssh *, Channel *);
|
||||
void chan_ibuf_empty(struct ssh *, Channel *);
|
||||
void chan_rcvd_ieof(struct ssh *, Channel *);
|
||||
void chan_write_failed(struct ssh *, Channel *);
|
||||
void chan_obuf_empty(struct ssh *, Channel *);
|
||||
|
||||
#endif
|
||||
|
@ -1,158 +0,0 @@
|
||||
/* $OpenBSD: cipher-3des1.c,v 1.12 2015/01/14 10:24:42 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2003 Markus Friedl. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "ssherr.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.
|
||||
*/
|
||||
struct ssh1_3des_ctx
|
||||
{
|
||||
EVP_CIPHER_CTX k1, k2, k3;
|
||||
};
|
||||
|
||||
const EVP_CIPHER * evp_ssh1_3des(void);
|
||||
int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
|
||||
|
||||
static int
|
||||
ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
|
||||
int enc)
|
||||
{
|
||||
struct ssh1_3des_ctx *c;
|
||||
u_char *k1, *k2, *k3;
|
||||
|
||||
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
|
||||
if ((c = calloc(1, sizeof(*c))) == NULL)
|
||||
return 0;
|
||||
EVP_CIPHER_CTX_set_app_data(ctx, c);
|
||||
}
|
||||
if (key == NULL)
|
||||
return 1;
|
||||
if (enc == -1)
|
||||
enc = ctx->encrypt;
|
||||
k1 = k2 = k3 = (u_char *) key;
|
||||
k2 += 8;
|
||||
if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
|
||||
if (enc)
|
||||
k3 += 16;
|
||||
else
|
||||
k1 += 16;
|
||||
}
|
||||
EVP_CIPHER_CTX_init(&c->k1);
|
||||
EVP_CIPHER_CTX_init(&c->k2);
|
||||
EVP_CIPHER_CTX_init(&c->k3);
|
||||
if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
|
||||
EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
|
||||
EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
|
||||
explicit_bzero(c, sizeof(*c));
|
||||
free(c);
|
||||
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len)
|
||||
{
|
||||
struct ssh1_3des_ctx *c;
|
||||
|
||||
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
|
||||
return 0;
|
||||
if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
|
||||
EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
|
||||
EVP_Cipher(&c->k3, dest, dest, len) == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
struct ssh1_3des_ctx *c;
|
||||
|
||||
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
|
||||
EVP_CIPHER_CTX_cleanup(&c->k1);
|
||||
EVP_CIPHER_CTX_cleanup(&c->k2);
|
||||
EVP_CIPHER_CTX_cleanup(&c->k3);
|
||||
explicit_bzero(c, sizeof(*c));
|
||||
free(c);
|
||||
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
|
||||
{
|
||||
struct ssh1_3des_ctx *c;
|
||||
|
||||
if (len != 24)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
if (doset) {
|
||||
memcpy(c->k1.iv, iv, 8);
|
||||
memcpy(c->k2.iv, iv + 8, 8);
|
||||
memcpy(c->k3.iv, iv + 16, 8);
|
||||
} else {
|
||||
memcpy(iv, c->k1.iv, 8);
|
||||
memcpy(iv + 8, c->k2.iv, 8);
|
||||
memcpy(iv + 16, c->k3.iv, 8);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const EVP_CIPHER *
|
||||
evp_ssh1_3des(void)
|
||||
{
|
||||
static EVP_CIPHER ssh1_3des;
|
||||
|
||||
memset(&ssh1_3des, 0, sizeof(ssh1_3des));
|
||||
ssh1_3des.nid = NID_undef;
|
||||
ssh1_3des.block_size = 8;
|
||||
ssh1_3des.iv_len = 0;
|
||||
ssh1_3des.key_len = 16;
|
||||
ssh1_3des.init = ssh1_3des_init;
|
||||
ssh1_3des.cleanup = ssh1_3des_cleanup;
|
||||
ssh1_3des.do_cipher = ssh1_3des_cbc;
|
||||
ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
|
||||
return &ssh1_3des;
|
||||
}
|
||||
#endif /* WITH_SSH1 */
|
@ -1,106 +0,0 @@
|
||||
/* $OpenBSD: cipher-bf1.c,v 1.7 2015/01/14 10:24:42 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2003 Markus Friedl. All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
#if defined(WITH_OPENSSL) && !defined(OPENSSL_NO_BF)
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
|
||||
/*
|
||||
* SSH1 uses a variation on Blowfish, all bytes must be swapped before
|
||||
* and after encryption/decryption. Thus the swap_bytes stuff (yuk).
|
||||
*/
|
||||
|
||||
const EVP_CIPHER * evp_ssh1_bf(void);
|
||||
|
||||
static void
|
||||
swap_bytes(const u_char *src, u_char *dst, int n)
|
||||
{
|
||||
u_char c[4];
|
||||
|
||||
/* Process 4 bytes every lap. */
|
||||
for (n = n / 4; n > 0; n--) {
|
||||
c[3] = *src++;
|
||||
c[2] = *src++;
|
||||
c[1] = *src++;
|
||||
c[0] = *src++;
|
||||
|
||||
*dst++ = c[0];
|
||||
*dst++ = c[1];
|
||||
*dst++ = c[2];
|
||||
*dst++ = c[3];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SSH_OLD_EVP
|
||||
static void bf_ssh1_init (EVP_CIPHER_CTX * ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc)
|
||||
{
|
||||
if (iv != NULL)
|
||||
memcpy (&(ctx->oiv[0]), iv, 8);
|
||||
memcpy (&(ctx->iv[0]), &(ctx->oiv[0]), 8);
|
||||
if (key != NULL)
|
||||
BF_set_key (&(ctx->c.bf_ks), EVP_CIPHER_CTX_key_length (ctx),
|
||||
key);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *,
|
||||
const u_char *, LIBCRYPTO_EVP_INL_TYPE) = NULL;
|
||||
|
||||
static int
|
||||
bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in,
|
||||
LIBCRYPTO_EVP_INL_TYPE len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
swap_bytes(in, out, len);
|
||||
ret = (*orig_bf)(ctx, out, out, len);
|
||||
swap_bytes(out, out, len);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
const EVP_CIPHER *
|
||||
evp_ssh1_bf(void)
|
||||
{
|
||||
static EVP_CIPHER ssh1_bf;
|
||||
|
||||
memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
|
||||
orig_bf = ssh1_bf.do_cipher;
|
||||
ssh1_bf.nid = NID_undef;
|
||||
#ifdef SSH_OLD_EVP
|
||||
ssh1_bf.init = bf_ssh1_init;
|
||||
#endif
|
||||
ssh1_bf.do_cipher = bf_ssh1_cipher;
|
||||
ssh1_bf.key_len = 32;
|
||||
return (&ssh1_bf);
|
||||
}
|
||||
#endif /* defined(WITH_OPENSSL) && !defined(OPENSSL_NO_BF) */
|
||||
|
||||
#endif /* WITH_SSH1 */
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cipher.c,v 1.102 2016/08/03 05:41:57 djm Exp $ */
|
||||
/* $OpenBSD: cipher.c,v 1.107 2017/05/07 23:12:57 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -51,11 +51,6 @@
|
||||
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
extern const EVP_CIPHER *evp_ssh1_bf(void);
|
||||
extern const EVP_CIPHER *evp_ssh1_3des(void);
|
||||
extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
|
||||
#endif
|
||||
|
||||
struct sshcipher_ctx {
|
||||
int plaintext;
|
||||
@ -68,17 +63,16 @@ struct sshcipher_ctx {
|
||||
|
||||
struct sshcipher {
|
||||
char *name;
|
||||
int number; /* for ssh1 only */
|
||||
u_int block_size;
|
||||
u_int key_len;
|
||||
u_int iv_len; /* defaults to block_size */
|
||||
u_int auth_len;
|
||||
u_int discard_len;
|
||||
u_int flags;
|
||||
#define CFLAG_CBC (1<<0)
|
||||
#define CFLAG_CHACHAPOLY (1<<1)
|
||||
#define CFLAG_AESCTR (1<<2)
|
||||
#define CFLAG_NONE (1<<3)
|
||||
#define CFLAG_INTERNAL CFLAG_NONE /* Don't use "none" for packets */
|
||||
#ifdef WITH_OPENSSL
|
||||
const EVP_CIPHER *(*evptype)(void);
|
||||
#else
|
||||
@ -87,53 +81,32 @@ struct sshcipher {
|
||||
};
|
||||
|
||||
static const struct sshcipher ciphers[] = {
|
||||
#ifdef WITH_SSH1
|
||||
{ "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
|
||||
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
|
||||
# ifndef OPENSSL_NO_BF
|
||||
{ "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf },
|
||||
# endif /* OPENSSL_NO_BF */
|
||||
#endif /* WITH_SSH1 */
|
||||
#ifdef WITH_OPENSSL
|
||||
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
|
||||
{ "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },
|
||||
# ifndef OPENSSL_NO_BF
|
||||
{ "blowfish-cbc",
|
||||
SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc },
|
||||
# endif /* OPENSSL_NO_BF */
|
||||
# ifndef OPENSSL_NO_CAST
|
||||
{ "cast128-cbc",
|
||||
SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_cast5_cbc },
|
||||
# endif /* OPENSSL_NO_CAST */
|
||||
# ifndef OPENSSL_NO_RC4
|
||||
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 0, EVP_rc4 },
|
||||
{ "arcfour128", SSH_CIPHER_SSH2, 8, 16, 0, 0, 1536, 0, EVP_rc4 },
|
||||
{ "arcfour256", SSH_CIPHER_SSH2, 8, 32, 0, 0, 1536, 0, EVP_rc4 },
|
||||
# endif /* OPENSSL_NO_RC4 */
|
||||
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc },
|
||||
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc },
|
||||
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
|
||||
{ "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc },
|
||||
{ "aes128-cbc", 16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc },
|
||||
{ "aes192-cbc", 16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc },
|
||||
{ "aes256-cbc", 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
|
||||
{ "rijndael-cbc@lysator.liu.se",
|
||||
SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
|
||||
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr },
|
||||
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr },
|
||||
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr },
|
||||
16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
|
||||
{ "aes128-ctr", 16, 16, 0, 0, 0, EVP_aes_128_ctr },
|
||||
{ "aes192-ctr", 16, 24, 0, 0, 0, EVP_aes_192_ctr },
|
||||
{ "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr },
|
||||
# ifdef OPENSSL_HAVE_EVPGCM
|
||||
{ "aes128-gcm@openssh.com",
|
||||
SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm },
|
||||
16, 16, 12, 16, 0, EVP_aes_128_gcm },
|
||||
{ "aes256-gcm@openssh.com",
|
||||
SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
|
||||
16, 32, 12, 16, 0, EVP_aes_256_gcm },
|
||||
# endif /* OPENSSL_HAVE_EVPGCM */
|
||||
#else /* WITH_OPENSSL */
|
||||
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL },
|
||||
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL },
|
||||
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL },
|
||||
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL },
|
||||
#endif /* WITH_OPENSSL */
|
||||
#else
|
||||
{ "aes128-ctr", 16, 16, 0, 0, CFLAG_AESCTR, NULL },
|
||||
{ "aes192-ctr", 16, 24, 0, 0, CFLAG_AESCTR, NULL },
|
||||
{ "aes256-ctr", 16, 32, 0, 0, CFLAG_AESCTR, NULL },
|
||||
#endif
|
||||
{ "chacha20-poly1305@openssh.com",
|
||||
SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL },
|
||||
8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL },
|
||||
{ "none", 8, 0, 0, 0, CFLAG_NONE, NULL },
|
||||
|
||||
{ NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
|
||||
{ NULL, 0, 0, 0, 0, 0, NULL }
|
||||
};
|
||||
|
||||
/*--*/
|
||||
@ -147,7 +120,7 @@ cipher_alg_list(char sep, int auth_only)
|
||||
const struct sshcipher *c;
|
||||
|
||||
for (c = ciphers; c->name != NULL; c++) {
|
||||
if (c->number != SSH_CIPHER_SSH2)
|
||||
if ((c->flags & CFLAG_INTERNAL) != 0)
|
||||
continue;
|
||||
if (auth_only && c->auth_len == 0)
|
||||
continue;
|
||||
@ -202,12 +175,6 @@ cipher_ivlen(const struct sshcipher *c)
|
||||
c->iv_len : c->block_size;
|
||||
}
|
||||
|
||||
u_int
|
||||
cipher_get_number(const struct sshcipher *c)
|
||||
{
|
||||
return (c->number);
|
||||
}
|
||||
|
||||
u_int
|
||||
cipher_is_cbc(const struct sshcipher *c)
|
||||
{
|
||||
@ -220,24 +187,6 @@ cipher_ctx_is_plaintext(struct sshcipher_ctx *cc)
|
||||
return cc->plaintext;
|
||||
}
|
||||
|
||||
u_int
|
||||
cipher_ctx_get_number(struct sshcipher_ctx *cc)
|
||||
{
|
||||
return cc->cipher->number;
|
||||
}
|
||||
|
||||
u_int
|
||||
cipher_mask_ssh1(int client)
|
||||
{
|
||||
u_int mask = 0;
|
||||
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
|
||||
mask |= 1 << SSH_CIPHER_BLOWFISH;
|
||||
if (client) {
|
||||
mask |= 1 << SSH_CIPHER_DES;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
const struct sshcipher *
|
||||
cipher_by_name(const char *name)
|
||||
{
|
||||
@ -248,16 +197,6 @@ cipher_by_name(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct sshcipher *
|
||||
cipher_by_number(int id)
|
||||
{
|
||||
const struct sshcipher *c;
|
||||
for (c = ciphers; c->name != NULL; c++)
|
||||
if (c->number == id)
|
||||
return c;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define CIPHER_SEP ","
|
||||
int
|
||||
ciphers_valid(const char *names)
|
||||
@ -273,7 +212,7 @@ ciphers_valid(const char *names)
|
||||
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
|
||||
(p = strsep(&cp, CIPHER_SEP))) {
|
||||
c = cipher_by_name(p);
|
||||
if (c == NULL || c->number != SSH_CIPHER_SSH2) {
|
||||
if (c == NULL || (c->flags & CFLAG_INTERNAL) != 0) {
|
||||
free(cipher_list);
|
||||
return 0;
|
||||
}
|
||||
@ -282,38 +221,12 @@ ciphers_valid(const char *names)
|
||||
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)
|
||||
{
|
||||
const struct sshcipher *c;
|
||||
if (name == NULL)
|
||||
return -1;
|
||||
for (c = ciphers; c->name != NULL; c++)
|
||||
if (strcasecmp(c->name, name) == 0)
|
||||
return c->number;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *
|
||||
cipher_name(int id)
|
||||
{
|
||||
const struct sshcipher *c = cipher_by_number(id);
|
||||
return (c==NULL) ? "<unknown>" : c->name;
|
||||
}
|
||||
|
||||
const char *
|
||||
cipher_warning_message(const struct sshcipher_ctx *cc)
|
||||
{
|
||||
if (cc == NULL || cc->cipher == NULL)
|
||||
return NULL;
|
||||
if (cc->cipher->number == SSH_CIPHER_DES)
|
||||
return "use of DES is strongly discouraged due to "
|
||||
"cryptographic weaknesses";
|
||||
/* XXX repurpose for CBC warning */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -327,19 +240,13 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
|
||||
#ifdef WITH_OPENSSL
|
||||
const EVP_CIPHER *type;
|
||||
int klen;
|
||||
u_char *junk, *discard;
|
||||
#endif
|
||||
|
||||
*ccp = NULL;
|
||||
if ((cc = calloc(sizeof(*cc), 1)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
|
||||
if (cipher->number == SSH_CIPHER_DES) {
|
||||
if (keylen > 8)
|
||||
keylen = 8;
|
||||
}
|
||||
|
||||
cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
|
||||
cc->plaintext = (cipher->flags & CFLAG_NONE) != 0;
|
||||
cc->encrypt = do_encrypt;
|
||||
|
||||
if (keylen < cipher->key_len ||
|
||||
@ -353,6 +260,10 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
|
||||
ret = chachapoly_init(&cc->cp_ctx, key, keylen);
|
||||
goto out;
|
||||
}
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
#ifndef WITH_OPENSSL
|
||||
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
|
||||
aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
|
||||
@ -360,10 +271,6 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
ret = SSH_ERR_INVALID_ARGUMENT;
|
||||
goto out;
|
||||
#else /* WITH_OPENSSL */
|
||||
@ -394,23 +301,6 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cipher->discard_len > 0) {
|
||||
if ((junk = malloc(cipher->discard_len)) == NULL ||
|
||||
(discard = malloc(cipher->discard_len)) == NULL) {
|
||||
free(junk);
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
ret = EVP_Cipher(cc->evp, discard, junk, cipher->discard_len);
|
||||
explicit_bzero(discard, cipher->discard_len);
|
||||
free(junk);
|
||||
free(discard);
|
||||
if (ret != 1) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
#endif /* WITH_OPENSSL */
|
||||
out:
|
||||
@ -448,6 +338,10 @@ cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
|
||||
return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src,
|
||||
len, aadlen, authlen, cc->encrypt);
|
||||
}
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0) {
|
||||
memcpy(dest, src, aadlen + len);
|
||||
return 0;
|
||||
}
|
||||
#ifndef WITH_OPENSSL
|
||||
if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
|
||||
if (aadlen)
|
||||
@ -456,10 +350,6 @@ cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
|
||||
dest + aadlen, len);
|
||||
return 0;
|
||||
}
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0) {
|
||||
memcpy(dest, src, aadlen + len);
|
||||
return 0;
|
||||
}
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
#else
|
||||
if (authlen) {
|
||||
@ -535,28 +425,6 @@ cipher_free(struct sshcipher_ctx *cc)
|
||||
free(cc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Selects the cipher, and keys if by computing the MD5 checksum of the
|
||||
* passphrase and using the resulting 16 bytes as the key.
|
||||
*/
|
||||
int
|
||||
cipher_set_key_string(struct sshcipher_ctx **ccp,
|
||||
const struct sshcipher *cipher, const char *passphrase, int do_encrypt)
|
||||
{
|
||||
u_char digest[16];
|
||||
int r = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
if ((r = ssh_digest_memory(SSH_DIGEST_MD5,
|
||||
passphrase, strlen(passphrase),
|
||||
digest, sizeof(digest))) != 0)
|
||||
goto out;
|
||||
|
||||
r = cipher_init(ccp, cipher, digest, 16, NULL, 0, do_encrypt);
|
||||
out:
|
||||
explicit_bzero(digest, sizeof(digest));
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exports an IV from the sshcipher_ctx required to export the key
|
||||
* state back from the unprivileged child to the privileged parent
|
||||
@ -566,19 +434,16 @@ int
|
||||
cipher_get_keyiv_len(const struct sshcipher_ctx *cc)
|
||||
{
|
||||
const struct sshcipher *c = cc->cipher;
|
||||
int ivlen = 0;
|
||||
|
||||
if (c->number == SSH_CIPHER_3DES)
|
||||
ivlen = 24;
|
||||
else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
|
||||
ivlen = 0;
|
||||
else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
|
||||
ivlen = sizeof(cc->ac_ctx.ctr);
|
||||
if ((c->flags & CFLAG_CHACHAPOLY) != 0)
|
||||
return 0;
|
||||
else if ((c->flags & CFLAG_AESCTR) != 0)
|
||||
return sizeof(cc->ac_ctx.ctr);
|
||||
#ifdef WITH_OPENSSL
|
||||
else
|
||||
ivlen = EVP_CIPHER_CTX_iv_length(cc->evp);
|
||||
#endif /* WITH_OPENSSL */
|
||||
return (ivlen);
|
||||
return EVP_CIPHER_CTX_iv_length(cc->evp);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@ -603,11 +468,7 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0)
|
||||
return 0;
|
||||
|
||||
switch (c->number) {
|
||||
#ifdef WITH_OPENSSL
|
||||
case SSH_CIPHER_SSH2:
|
||||
case SSH_CIPHER_DES:
|
||||
case SSH_CIPHER_BLOWFISH:
|
||||
evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
|
||||
if (evplen == 0)
|
||||
return 0;
|
||||
@ -626,15 +487,7 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
} else
|
||||
memcpy(iv, cc->evp->iv, len);
|
||||
break;
|
||||
#endif
|
||||
#ifdef WITH_SSH1
|
||||
case SSH_CIPHER_3DES:
|
||||
return ssh1_3des_iv(cc->evp, 0, iv, 24);
|
||||
#endif
|
||||
default:
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -651,11 +504,7 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
|
||||
if ((cc->cipher->flags & CFLAG_NONE) != 0)
|
||||
return 0;
|
||||
|
||||
switch (c->number) {
|
||||
#ifdef WITH_OPENSSL
|
||||
case SSH_CIPHER_SSH2:
|
||||
case SSH_CIPHER_DES:
|
||||
case SSH_CIPHER_BLOWFISH:
|
||||
evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
|
||||
if (evplen <= 0)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
@ -672,15 +521,7 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
} else
|
||||
memcpy(cc->evp->iv, iv, evplen);
|
||||
break;
|
||||
#endif
|
||||
#ifdef WITH_SSH1
|
||||
case SSH_CIPHER_3DES:
|
||||
return ssh1_3des_iv(cc->evp, 1, (u_char *)iv, 24);
|
||||
#endif
|
||||
default:
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cipher.h,v 1.49 2016/08/03 05:41:57 djm Exp $ */
|
||||
/* $OpenBSD: cipher.h,v 1.52 2017/05/07 23:12:57 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -42,34 +42,13 @@
|
||||
#include "cipher-chachapoly.h"
|
||||
#include "cipher-aesctr.h"
|
||||
|
||||
/*
|
||||
* Cipher types for SSH-1. New types can be added, but old types should not
|
||||
* be removed for compatibility. The maximum allowed value is 31.
|
||||
*/
|
||||
#define SSH_CIPHER_SSH2 -3
|
||||
#define SSH_CIPHER_INVALID -2 /* No valid cipher selected. */
|
||||
#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */
|
||||
#define SSH_CIPHER_NONE 0 /* no encryption */
|
||||
#define SSH_CIPHER_IDEA 1 /* IDEA CFB */
|
||||
#define SSH_CIPHER_DES 2 /* DES CBC */
|
||||
#define SSH_CIPHER_3DES 3 /* 3DES CBC */
|
||||
#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */
|
||||
#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
|
||||
#define SSH_CIPHER_BLOWFISH 6
|
||||
#define SSH_CIPHER_RESERVED 7
|
||||
#define SSH_CIPHER_MAX 31
|
||||
|
||||
#define CIPHER_ENCRYPT 1
|
||||
#define CIPHER_DECRYPT 0
|
||||
|
||||
struct sshcipher;
|
||||
struct sshcipher_ctx;
|
||||
|
||||
u_int cipher_mask_ssh1(int);
|
||||
const struct sshcipher *cipher_by_name(const char *);
|
||||
const struct sshcipher *cipher_by_number(int);
|
||||
int cipher_number(const char *);
|
||||
char *cipher_name(int);
|
||||
const char *cipher_warning_message(const struct sshcipher_ctx *);
|
||||
int ciphers_valid(const char *);
|
||||
char *cipher_alg_list(char, int);
|
||||
@ -80,8 +59,6 @@ int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *,
|
||||
int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int,
|
||||
const u_char *, u_int);
|
||||
void cipher_free(struct sshcipher_ctx *);
|
||||
int cipher_set_key_string(struct sshcipher_ctx **,
|
||||
const struct sshcipher *, const char *, int);
|
||||
u_int cipher_blocksize(const struct sshcipher *);
|
||||
u_int cipher_keylen(const struct sshcipher *);
|
||||
u_int cipher_seclen(const struct sshcipher *);
|
||||
@ -90,13 +67,9 @@ u_int cipher_ivlen(const struct sshcipher *);
|
||||
u_int cipher_is_cbc(const struct sshcipher *);
|
||||
|
||||
u_int cipher_ctx_is_plaintext(struct sshcipher_ctx *);
|
||||
u_int cipher_ctx_get_number(struct sshcipher_ctx *);
|
||||
|
||||
u_int cipher_get_number(const struct sshcipher *);
|
||||
int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int);
|
||||
int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *);
|
||||
int cipher_get_keyiv_len(const struct sshcipher_ctx *);
|
||||
int cipher_get_keycontext(const struct sshcipher_ctx *, u_char *);
|
||||
void cipher_set_keycontext(struct sshcipher_ctx *, const u_char *);
|
||||
|
||||
#endif /* CIPHER_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: clientloop.h,v 1.33 2016/09/30 09:19:13 markus Exp $ */
|
||||
/* $OpenBSD: clientloop.h,v 1.34 2017/09/12 06:32:07 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -37,28 +37,31 @@
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
struct ssh;
|
||||
|
||||
/* Client side main loop for the interactive session. */
|
||||
int client_loop(int, int, int);
|
||||
int client_x11_get_proto(const char *, const char *, u_int, u_int,
|
||||
char **, char **);
|
||||
int client_loop(struct ssh *, int, int, int);
|
||||
int client_x11_get_proto(struct ssh *, const char *, const char *,
|
||||
u_int, u_int, char **, char **);
|
||||
void client_global_request_reply_fwd(int, u_int32_t, void *);
|
||||
void client_session2_setup(int, int, int, const char *, struct termios *,
|
||||
int, Buffer *, char **);
|
||||
int client_request_tun_fwd(int, int, int);
|
||||
void client_session2_setup(struct ssh *, int, int, int,
|
||||
const char *, struct termios *, int, Buffer *, char **);
|
||||
int client_request_tun_fwd(struct ssh *, int, int, int);
|
||||
void client_stop_mux(void);
|
||||
|
||||
/* Escape filter for protocol 2 sessions */
|
||||
void *client_new_escape_filter_ctx(int);
|
||||
void client_filter_cleanup(int, void *);
|
||||
int client_simple_escape_filter(Channel *, char *, int);
|
||||
void client_filter_cleanup(struct ssh *, int, void *);
|
||||
int client_simple_escape_filter(struct ssh *, Channel *, char *, int);
|
||||
|
||||
/* Global request confirmation callbacks */
|
||||
typedef void global_confirm_cb(int, u_int32_t seq, void *);
|
||||
typedef void global_confirm_cb(struct ssh *, int, u_int32_t, void *);
|
||||
void client_register_global_confirm(global_confirm_cb *, void *);
|
||||
|
||||
/* Channel request confirmation callbacks */
|
||||
enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY };
|
||||
void client_expect_confirm(int, const char *, enum confirm_action);
|
||||
void client_expect_confirm(struct ssh *, int, const char *,
|
||||
enum confirm_action);
|
||||
|
||||
/* Multiplexing protocol version */
|
||||
#define SSHMUX_VER 4
|
||||
@ -73,8 +76,8 @@ void client_expect_confirm(int, const char *, enum confirm_action);
|
||||
#define SSHMUX_COMMAND_CANCEL_FWD 7 /* Cancel forwarding(s) */
|
||||
#define SSHMUX_COMMAND_PROXY 8 /* Open new connection */
|
||||
|
||||
void muxserver_listen(void);
|
||||
void muxserver_listen(struct ssh *);
|
||||
int muxclient(const char *);
|
||||
void mux_exit_message(Channel *, int);
|
||||
void mux_tty_alloc_failed(Channel *);
|
||||
void mux_exit_message(struct ssh *, Channel *, int);
|
||||
void mux_tty_alloc_failed(struct ssh *ssh, Channel *);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: compat.c,v 1.100 2017/02/03 23:01:19 djm Exp $ */
|
||||
/* $OpenBSD: compat.c,v 1.104 2017/07/25 09:22:25 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -39,24 +39,8 @@
|
||||
#include "match.h"
|
||||
#include "kex.h"
|
||||
|
||||
int compat13 = 0;
|
||||
int compat20 = 0;
|
||||
int datafellows = 0;
|
||||
|
||||
void
|
||||
enable_compat20(void)
|
||||
{
|
||||
if (compat20)
|
||||
return;
|
||||
debug("Enabling compatibility mode for protocol 2.0");
|
||||
compat20 = 1;
|
||||
}
|
||||
void
|
||||
enable_compat13(void)
|
||||
{
|
||||
debug("Enabling compatibility mode for protocol 1.3");
|
||||
compat13 = 1;
|
||||
}
|
||||
/* datafellows bug compatibility */
|
||||
u_int
|
||||
compat_datafellows(const char *version)
|
||||
@ -193,9 +177,12 @@ compat_datafellows(const char *version)
|
||||
"TTSSH/2.72*", SSH_BUG_HOSTKEYS },
|
||||
{ "WinSCP_release_4*,"
|
||||
"WinSCP_release_5.0*,"
|
||||
"WinSCP_release_5.1*,"
|
||||
"WinSCP_release_5.5*,"
|
||||
"WinSCP_release_5.6*,"
|
||||
"WinSCP_release_5.1,"
|
||||
"WinSCP_release_5.1.*,"
|
||||
"WinSCP_release_5.5,"
|
||||
"WinSCP_release_5.5.*,"
|
||||
"WinSCP_release_5.6,"
|
||||
"WinSCP_release_5.6.*,"
|
||||
"WinSCP_release_5.7,"
|
||||
"WinSCP_release_5.7.1,"
|
||||
"WinSCP_release_5.7.2,"
|
||||
@ -232,13 +219,6 @@ proto_spec(const char *spec)
|
||||
return ret;
|
||||
for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) {
|
||||
switch (atoi(p)) {
|
||||
case 1:
|
||||
#ifdef WITH_SSH1
|
||||
if (ret == SSH_PROTO_UNKNOWN)
|
||||
ret |= SSH_PROTO_1_PREFERRED;
|
||||
ret |= SSH_PROTO_1;
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
ret |= SSH_PROTO_2;
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: compat.h,v 1.48 2015/05/26 23:23:40 dtucker Exp $ */
|
||||
/* $OpenBSD: compat.h,v 1.49 2017/04/30 23:13:25 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
|
||||
@ -63,15 +63,11 @@
|
||||
#define SSH_BUG_HOSTKEYS 0x20000000
|
||||
#define SSH_BUG_DHGEX_LARGE 0x40000000
|
||||
|
||||
void enable_compat13(void);
|
||||
void enable_compat20(void);
|
||||
u_int compat_datafellows(const char *);
|
||||
int proto_spec(const char *);
|
||||
char *compat_cipher_proposal(char *);
|
||||
char *compat_pkalg_proposal(char *);
|
||||
char *compat_kex_proposal(char *);
|
||||
|
||||
extern int compat13;
|
||||
extern int compat20;
|
||||
extern int datafellows;
|
||||
#endif
|
||||
|
@ -253,6 +253,9 @@
|
||||
/* Define to 1 if you have the <bstring.h> header file. */
|
||||
/* #undef HAVE_BSTRING_H */
|
||||
|
||||
/* calloc(x, 0) returns NULL */
|
||||
/* #undef HAVE_CALLOC */
|
||||
|
||||
/* Define to 1 if you have the `cap_rights_limit' function. */
|
||||
#define HAVE_CAP_RIGHTS_LIMIT 1
|
||||
|
||||
@ -470,6 +473,9 @@
|
||||
/* Define to 1 if you have the `freeaddrinfo' function. */
|
||||
#define HAVE_FREEADDRINFO 1
|
||||
|
||||
/* Define to 1 if you have the `freezero' function. */
|
||||
/* #undef HAVE_FREEZERO */
|
||||
|
||||
/* Define to 1 if the system has the type `fsblkcnt_t'. */
|
||||
#define HAVE_FSBLKCNT_T 1
|
||||
|
||||
@ -770,6 +776,10 @@
|
||||
/* Define to 1 if you have the <maillock.h> header file. */
|
||||
/* #undef HAVE_MAILLOCK_H */
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */
|
||||
#define HAVE_MALLOC 1
|
||||
|
||||
/* Define to 1 if you have the `mblen' function. */
|
||||
#define HAVE_MBLEN 1
|
||||
|
||||
@ -900,12 +910,19 @@
|
||||
/* Define to 1 if you have the <readpassphrase.h> header file. */
|
||||
#define HAVE_READPASSPHRASE_H 1
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
|
||||
and to 0 otherwise. */
|
||||
#define HAVE_REALLOC 1
|
||||
|
||||
/* Define to 1 if you have the `reallocarray' function. */
|
||||
#define HAVE_REALLOCARRAY 1
|
||||
|
||||
/* Define to 1 if you have the `realpath' function. */
|
||||
#define HAVE_REALPATH 1
|
||||
|
||||
/* Define to 1 if you have the `recallocarray' function. */
|
||||
/* #undef HAVE_RECALLOCARRAY */
|
||||
|
||||
/* Define to 1 if you have the `recvmsg' function. */
|
||||
#define HAVE_RECVMSG 1
|
||||
|
||||
@ -1116,6 +1133,9 @@
|
||||
/* Define to 1 if you have the `strsep' function. */
|
||||
#define HAVE_STRSEP 1
|
||||
|
||||
/* Define to 1 if you have the `strsignal' function. */
|
||||
#define HAVE_STRSIGNAL 1
|
||||
|
||||
/* Define to 1 if you have the `strtoll' function. */
|
||||
#define HAVE_STRTOLL 1
|
||||
|
||||
@ -1158,6 +1178,12 @@
|
||||
/* Define to 1 if `st_blksize' is a member of `struct stat'. */
|
||||
#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
|
||||
|
||||
/* Define to 1 if `st_mtim' is a member of `struct stat'. */
|
||||
#define HAVE_STRUCT_STAT_ST_MTIM 1
|
||||
|
||||
/* Define to 1 if `st_mtime' is a member of `struct stat'. */
|
||||
#define HAVE_STRUCT_STAT_ST_MTIME 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct timespec'. */
|
||||
#define HAVE_STRUCT_TIMESPEC 1
|
||||
|
||||
@ -1723,9 +1749,6 @@
|
||||
/* Define if you want SELinux support. */
|
||||
/* #undef WITH_SELINUX */
|
||||
|
||||
/* include SSH protocol version 1 support */
|
||||
/* #undef WITH_SSH1 */
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||
@ -1764,11 +1787,20 @@
|
||||
/* Define if we don't have struct __res_state in resolv.h */
|
||||
/* #undef __res_state */
|
||||
|
||||
/* Define to rpl_calloc if the replacement function should be used. */
|
||||
/* #undef calloc */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define to rpl_malloc if the replacement function should be used. */
|
||||
/* #undef malloc */
|
||||
|
||||
/* Define to rpl_realloc if the replacement function should be used. */
|
||||
/* #undef realloc */
|
||||
|
||||
/* type to use in place of socklen_t if not defined */
|
||||
/* #undef socklen_t */
|
||||
|
@ -110,13 +110,10 @@ AC_CHECK_DECL([PR_SET_NO_NEW_PRIVS], [have_linux_no_new_privs=1], , [
|
||||
])
|
||||
|
||||
openssl=yes
|
||||
ssh1=no
|
||||
COMMENT_OUT_RSA1="#no ssh1#"
|
||||
AC_ARG_WITH([openssl],
|
||||
[ --without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL** ],
|
||||
[ if test "x$withval" = "xno" ; then
|
||||
openssl=no
|
||||
ssh1=no
|
||||
fi
|
||||
]
|
||||
)
|
||||
@ -128,31 +125,6 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([ssh1],
|
||||
[ --with-ssh1 Enable support for SSH protocol 1],
|
||||
[
|
||||
if test "x$withval" = "xyes" ; then
|
||||
if test "x$openssl" = "xno" ; then
|
||||
AC_MSG_ERROR([Cannot enable SSH protocol 1 with OpenSSL disabled])
|
||||
fi
|
||||
ssh1=yes
|
||||
COMMENT_OUT_RSA1=""
|
||||
elif test "x$withval" = "xno" ; then
|
||||
ssh1=no
|
||||
else
|
||||
AC_MSG_ERROR([unknown --with-ssh1 argument])
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_MSG_CHECKING([whether SSH protocol 1 support is enabled])
|
||||
if test "x$ssh1" = "xyes" ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE_UNQUOTED([WITH_SSH1], [1], [include SSH protocol version 1 support])
|
||||
AC_SUBST([COMMENT_OUT_RSA1])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
use_stack_protector=1
|
||||
use_toolchain_hardening=1
|
||||
AC_ARG_WITH([stackprotect],
|
||||
@ -180,6 +152,7 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int main(void) { return 0; }]])],
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
|
||||
if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
|
||||
OSSH_CHECK_CFLAG_COMPILE([-pipe])
|
||||
OSSH_CHECK_CFLAG_COMPILE([-Qunused-arguments])
|
||||
OSSH_CHECK_CFLAG_COMPILE([-Wunknown-warning-option])
|
||||
OSSH_CHECK_CFLAG_COMPILE([-Wall])
|
||||
@ -191,8 +164,8 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
|
||||
OSSH_CHECK_CFLAG_COMPILE([-Wpointer-sign], [-Wno-pointer-sign])
|
||||
OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result])
|
||||
OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing])
|
||||
OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2])
|
||||
if test "x$use_toolchain_hardening" = "x1"; then
|
||||
OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2])
|
||||
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,relro])
|
||||
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,now])
|
||||
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,noexecstack])
|
||||
@ -317,6 +290,16 @@ AC_ARG_WITH([cflags],
|
||||
fi
|
||||
]
|
||||
)
|
||||
|
||||
AC_ARG_WITH([cflags-after],
|
||||
[ --with-cflags-after Specify additional flags to pass to compiler after configure],
|
||||
[
|
||||
if test -n "$withval" && test "x$withval" != "xno" && \
|
||||
test "x${withval}" != "xyes"; then
|
||||
CFLAGS_AFTER="$withval"
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_ARG_WITH([cppflags],
|
||||
[ --with-cppflags Specify additional flags to pass to preprocessor] ,
|
||||
[
|
||||
@ -335,6 +318,15 @@ AC_ARG_WITH([ldflags],
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_ARG_WITH([ldflags-after],
|
||||
[ --with-ldflags-after Specify additional flags to pass to linker after configure],
|
||||
[
|
||||
if test -n "$withval" && test "x$withval" != "xno" && \
|
||||
test "x${withval}" != "xyes"; then
|
||||
LDFLAGS_AFTER="$withval"
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_ARG_WITH([libs],
|
||||
[ --with-libs Specify additional libraries to link with],
|
||||
[
|
||||
@ -1014,6 +1006,7 @@ mips-sony-bsd|mips-sony-newsos4)
|
||||
AC_DEFINE([BROKEN_SETREUID])
|
||||
AC_DEFINE([BROKEN_SETREGID])
|
||||
AC_DEFINE([PASSWD_NEEDS_USERNAME])
|
||||
AC_DEFINE([BROKEN_TCGETATTR_ICANON])
|
||||
TEST_SHELL=$SHELL # let configure find us a capable shell
|
||||
case "$host" in
|
||||
*-*-sysv5SCO_SV*) # SCO OpenServer 6.x
|
||||
@ -1339,7 +1332,17 @@ AC_CHECK_FUNCS([fmt_scaled scan_scaled login logout openpty updwtmp logwtmp])
|
||||
AC_SEARCH_LIBS([inet_ntop], [resolv nsl])
|
||||
AC_SEARCH_LIBS([gethostbyname], [resolv nsl])
|
||||
|
||||
# "Particular Function Checks"
|
||||
# see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html
|
||||
AC_FUNC_STRFTIME
|
||||
AC_FUNC_MALLOC
|
||||
AC_FUNC_REALLOC
|
||||
# autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL;
|
||||
if test "x$ac_cv_func_malloc_0_nonnull" != "xyes"; then
|
||||
AC_DEFINE(HAVE_CALLOC, 0, [calloc(x, 0) returns NULL])
|
||||
AC_DEFINE(calloc, rpl_calloc,
|
||||
[Define to rpl_calloc if the replacement function should be used.])
|
||||
fi
|
||||
|
||||
# Check for ALTDIRFUNC glob() extension
|
||||
AC_MSG_CHECKING([for GLOB_ALTDIRFUNC support])
|
||||
@ -1548,6 +1551,7 @@ AC_ARG_WITH(ldns,
|
||||
else
|
||||
LIBS="$LIBS `$LDNSCONFIG --libs`"
|
||||
CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`"
|
||||
ldns=yes
|
||||
fi
|
||||
elif test "x$withval" != "xno" ; then
|
||||
CPPFLAGS="$CPPFLAGS -I${withval}/include"
|
||||
@ -1758,6 +1762,7 @@ AC_CHECK_FUNCS([ \
|
||||
fchmod \
|
||||
fchown \
|
||||
freeaddrinfo \
|
||||
freezero \
|
||||
fstatfs \
|
||||
fstatvfs \
|
||||
futimes \
|
||||
@ -1766,6 +1771,7 @@ AC_CHECK_FUNCS([ \
|
||||
getgrouplist \
|
||||
getnameinfo \
|
||||
getopt \
|
||||
getpagesize \
|
||||
getpeereid \
|
||||
getpeerucred \
|
||||
getpgid \
|
||||
@ -1796,6 +1802,7 @@ AC_CHECK_FUNCS([ \
|
||||
readpassphrase \
|
||||
reallocarray \
|
||||
recvmsg \
|
||||
recallocarray \
|
||||
rresvport_af \
|
||||
sendmsg \
|
||||
setdtablesize \
|
||||
@ -1829,6 +1836,7 @@ AC_CHECK_FUNCS([ \
|
||||
strnlen \
|
||||
strnvis \
|
||||
strptime \
|
||||
strsignal \
|
||||
strtonum \
|
||||
strtoll \
|
||||
strtoul \
|
||||
@ -2597,7 +2605,11 @@ if test "x$openssl" = "xyes" ; then
|
||||
10000*|0*)
|
||||
AC_MSG_ERROR([OpenSSL >= 1.0.1 required (have "$ssl_library_ver")])
|
||||
;;
|
||||
*) ;;
|
||||
100*) ;; # 1.0.x
|
||||
200*) ;; # LibreSSL
|
||||
*)
|
||||
AC_MSG_ERROR([OpenSSL >= 1.1.0 is not yet supported (have "$ssl_library_ver")])
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([$ssl_library_ver])
|
||||
],
|
||||
@ -2830,9 +2842,6 @@ if test "x$openssl" = "xyes" ; then
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */
|
||||
# error "OpenSSL < 0.9.8g has unreliable ECC code"
|
||||
#endif
|
||||
]], [[
|
||||
EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
const EVP_MD *m = EVP_sha256(); /* We need this too */
|
||||
@ -2851,9 +2860,6 @@ if test "x$openssl" = "xyes" ; then
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */
|
||||
# error "OpenSSL < 0.9.8g has unreliable ECC code"
|
||||
#endif
|
||||
]], [[
|
||||
EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1);
|
||||
const EVP_MD *m = EVP_sha384(); /* We need this too */
|
||||
@ -2872,9 +2878,6 @@ if test "x$openssl" = "xyes" ; then
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#if OPENSSL_VERSION_NUMBER < 0x0090807f /* 0.9.8g */
|
||||
# error "OpenSSL < 0.9.8g has unreliable ECC code"
|
||||
#endif
|
||||
]], [[
|
||||
EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1);
|
||||
const EVP_MD *m = EVP_sha512(); /* We need this too */
|
||||
@ -3259,7 +3262,8 @@ AC_RUN_IFELSE(
|
||||
select_works_with_rlimit=yes],
|
||||
[AC_MSG_RESULT([no])
|
||||
select_works_with_rlimit=no],
|
||||
[AC_MSG_WARN([cross compiling: assuming yes])]
|
||||
[AC_MSG_WARN([cross compiling: assuming yes])
|
||||
select_works_with_rlimit=yes]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([if setrlimit(RLIMIT_NOFILE,{0,0}) works])
|
||||
@ -3285,7 +3289,8 @@ AC_RUN_IFELSE(
|
||||
rlimit_nofile_zero_works=yes],
|
||||
[AC_MSG_RESULT([no])
|
||||
rlimit_nofile_zero_works=no],
|
||||
[AC_MSG_WARN([cross compiling: assuming yes])]
|
||||
[AC_MSG_WARN([cross compiling: assuming yes])
|
||||
rlimit_nofile_zero_works=yes]
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING([if setrlimit RLIMIT_FSIZE works])
|
||||
@ -3907,6 +3912,8 @@ OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmpx.h], [HAVE_TIME_IN_UTMPX])
|
||||
OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmpx.h], [HAVE_TV_IN_UTMPX])
|
||||
|
||||
AC_CHECK_MEMBERS([struct stat.st_blksize])
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtim])
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtime])
|
||||
AC_CHECK_MEMBERS([struct passwd.pw_gecos, struct passwd.pw_class,
|
||||
struct passwd.pw_change, struct passwd.pw_expire],
|
||||
[], [], [[
|
||||
@ -5106,6 +5113,9 @@ AC_SUBST([TEST_SSH_UTF8], [$TEST_SSH_UTF8])
|
||||
AC_SUBST([TEST_MALLOC_OPTIONS], [$TEST_MALLOC_OPTIONS])
|
||||
AC_SUBST([UNSUPPORTED_ALGORITHMS], [$unsupported_algorithms])
|
||||
|
||||
CFLAGS="${CFLAGS} ${CFLAGS_AFTER}"
|
||||
LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}"
|
||||
|
||||
AC_EXEEXT
|
||||
AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
|
||||
openbsd-compat/Makefile openbsd-compat/regress/Makefile \
|
||||
|
@ -35,7 +35,7 @@ The script treats all packages as USR packages (not ROOT+USR when
|
||||
appropriate). It seems to work, though......
|
||||
|
||||
If there are any patches to this that have not yet been integrated they
|
||||
may be found at http://www.zip.com.au/~dtucker/openssh/.
|
||||
may be found at http://www.dtucker.net/openssh/.
|
||||
|
||||
|
||||
Disclaimer:
|
||||
|
@ -1,4 +1,4 @@
|
||||
%define ver 7.5p1
|
||||
%define ver 7.6p1
|
||||
%define rel 1
|
||||
|
||||
# OpenSSH privilege separation requires a user & group ID
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (c) 1999-2013 Philip Hands <phil@hands.com>
|
||||
# Copyright (c) 1999-2016 Philip Hands <phil@hands.com>
|
||||
# 2013 Martin Kletzander <mkletzan@redhat.com>
|
||||
# 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= <asp16@alu.ua.es>
|
||||
# 2010 Eric Moret <eric.moret@gmail.com>
|
||||
@ -56,7 +56,8 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
DEFAULT_PUB_ID_FILE="$HOME/$(cd "$HOME" ; ls -t .ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)"
|
||||
most_recent_id="$(cd "$HOME" ; ls -t .ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)"
|
||||
DEFAULT_PUB_ID_FILE="${most_recent_id:+$HOME/}$most_recent_id"
|
||||
|
||||
usage () {
|
||||
printf 'Usage: %s [-h|-?|-f|-n] [-i [identity_file]] [-p port] [[-o <ssh -o options>] ...] [user@]hostname\n' "$0" >&2
|
||||
@ -74,6 +75,11 @@ quote() {
|
||||
use_id_file() {
|
||||
local L_ID_FILE="$1"
|
||||
|
||||
if [ -z "$L_ID_FILE" ] ; then
|
||||
printf "%s: ERROR: no ID file found\n" "$0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if expr "$L_ID_FILE" : ".*\.pub$" >/dev/null ; then
|
||||
PUB_ID_FILE="$L_ID_FILE"
|
||||
else
|
||||
@ -287,9 +293,10 @@ case "$REMOTE_VERSION" in
|
||||
*)
|
||||
# Assuming that the remote host treats ~/.ssh/authorized_keys as one might expect
|
||||
populate_new_ids 0
|
||||
# in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX; 'cd' to be at $HOME; and all on one line, because tcsh.
|
||||
# in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX;
|
||||
# 'cd' to be at $HOME; add a newline if it's missing; and all on one line, because tcsh.
|
||||
[ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \
|
||||
ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \
|
||||
ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys ; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \
|
||||
|| exit 1
|
||||
ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l)
|
||||
;;
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation
|
||||
Name: openssh
|
||||
Version: 7.5p1
|
||||
Version: 7.6p1
|
||||
URL: https://www.openssh.com/
|
||||
Release: 1
|
||||
Source0: openssh-%{version}.tar.gz
|
||||
|
@ -1,165 +0,0 @@
|
||||
/* $OpenBSD: deattack.c,v 1.32 2015/01/20 23:14:00 deraadt 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>
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "deattack.h"
|
||||
#include "crc32.h"
|
||||
#include "sshbuf.h"
|
||||
#include "misc.h"
|
||||
|
||||
/*
|
||||
* CRC attack detection has a worst-case behaviour that is O(N^3) over
|
||||
* the number of identical blocks in a packet. This behaviour can be
|
||||
* exploited to create a limited denial of service attack.
|
||||
*
|
||||
* However, because we are dealing with encrypted data, identical
|
||||
* blocks should only occur every 2^35 maximally-sized packets or so.
|
||||
* Consequently, we can detect this DoS by looking for identical blocks
|
||||
* in a packet.
|
||||
*
|
||||
* The parameter below determines how many identical blocks we will
|
||||
* accept in a single packet, trading off between attack detection and
|
||||
* likelihood of terminating a legitimate connection. A value of 32
|
||||
* corresponds to an average of 2^40 messages before an attack is
|
||||
* misdetected
|
||||
*/
|
||||
#define MAX_IDENTICAL 32
|
||||
|
||||
/* 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) PEEK_U32(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((u_char *)&b, sizeof(b));
|
||||
}
|
||||
|
||||
/* detect if a block is used in a particular pattern */
|
||||
static int
|
||||
check_crc(const u_char *S, const u_char *buf, u_int32_t len)
|
||||
{
|
||||
u_int32_t crc;
|
||||
const u_char *c;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
deattack_init(struct deattack_ctx *dctx)
|
||||
{
|
||||
bzero(dctx, sizeof(*dctx));
|
||||
dctx->n = HASH_MINSIZE / HASH_ENTRYSIZE;
|
||||
}
|
||||
|
||||
/* Detect a crc32 compensation attack on a packet */
|
||||
int
|
||||
detect_attack(struct deattack_ctx *dctx, const u_char *buf, u_int32_t len)
|
||||
{
|
||||
u_int32_t i, j, l, same;
|
||||
u_int16_t *tmp;
|
||||
const u_char *c, *d;
|
||||
|
||||
if (len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
|
||||
len % SSH_BLOCKSIZE != 0)
|
||||
return DEATTACK_ERROR;
|
||||
for (l = dctx->n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2)
|
||||
;
|
||||
|
||||
if (dctx->h == NULL) {
|
||||
if ((dctx->h = calloc(l, HASH_ENTRYSIZE)) == NULL)
|
||||
return DEATTACK_ERROR;
|
||||
dctx->n = l;
|
||||
} else {
|
||||
if (l > dctx->n) {
|
||||
if ((tmp = reallocarray(dctx->h, l, HASH_ENTRYSIZE))
|
||||
== NULL) {
|
||||
free(dctx->h);
|
||||
dctx->h = NULL;
|
||||
return DEATTACK_ERROR;
|
||||
}
|
||||
dctx->h = tmp;
|
||||
dctx->n = l;
|
||||
}
|
||||
}
|
||||
|
||||
if (len <= HASH_MINBLOCKS) {
|
||||
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
|
||||
for (d = buf; d < c; d += SSH_BLOCKSIZE) {
|
||||
if (!CMP(c, d)) {
|
||||
if ((check_crc(c, buf, len)))
|
||||
return DEATTACK_DETECTED;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return DEATTACK_OK;
|
||||
}
|
||||
memset(dctx->h, HASH_UNUSEDCHAR, dctx->n * HASH_ENTRYSIZE);
|
||||
|
||||
for (c = buf, same = j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) {
|
||||
for (i = HASH(c) & (dctx->n - 1); dctx->h[i] != HASH_UNUSED;
|
||||
i = (i + 1) & (dctx->n - 1)) {
|
||||
if (!CMP(c, buf + dctx->h[i] * SSH_BLOCKSIZE)) {
|
||||
if (++same > MAX_IDENTICAL)
|
||||
return DEATTACK_DOS_DETECTED;
|
||||
if (check_crc(c, buf, len))
|
||||
return DEATTACK_DETECTED;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
dctx->h[i] = j;
|
||||
}
|
||||
return DEATTACK_OK;
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
/* $OpenBSD: deattack.h,v 1.11 2015/01/19 19:52:16 markus 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
|
||||
#define DEATTACK_DOS_DETECTED 2
|
||||
#define DEATTACK_ERROR 3
|
||||
|
||||
struct deattack_ctx {
|
||||
u_int16_t *h;
|
||||
u_int32_t n;
|
||||
};
|
||||
|
||||
void deattack_init(struct deattack_ctx *);
|
||||
int detect_attack(struct deattack_ctx *, const u_char *, u_int32_t);
|
||||
#endif
|
@ -328,6 +328,28 @@ typedef unsigned int size_t;
|
||||
#define SIZE_MAX SIZE_T_MAX
|
||||
#endif
|
||||
|
||||
#ifndef INT32_MAX
|
||||
# if (SIZEOF_INT == 4)
|
||||
# define INT32_MAX INT_MAX
|
||||
# elif (SIZEOF_LONG == 4)
|
||||
# define INT32_MAX LONG_MAX
|
||||
# else
|
||||
# error "need INT32_MAX"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef INT64_MAX
|
||||
# if (SIZEOF_INT == 8)
|
||||
# define INT64_MAX INT_MAX
|
||||
# elif (SIZEOF_LONG == 8)
|
||||
# define INT64_MAX LONG_MAX
|
||||
# elif (SIZEOF_LONG_LONG_INT == 8)
|
||||
# define INT64_MAX LLONG_MAX
|
||||
# else
|
||||
# error "need INT64_MAX"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SSIZE_T
|
||||
typedef int ssize_t;
|
||||
# define HAVE_SSIZE_T
|
||||
@ -497,6 +519,13 @@ struct winsize {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef timespeccmp
|
||||
#define timespeccmp(tsp, usp, cmp) \
|
||||
(((tsp)->tv_sec == (usp)->tv_sec) ? \
|
||||
((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
|
||||
((tsp)->tv_sec cmp (usp)->tv_sec))
|
||||
#endif
|
||||
|
||||
#ifndef __P
|
||||
# define __P(x) x
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: digest-libc.c,v 1.5 2015/05/05 02:48:17 jsg Exp $ */
|
||||
/* $OpenBSD: digest-libc.c,v 1.6 2017/05/08 22:57:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
|
||||
* Copyright (c) 2014 Markus Friedl. All rights reserved.
|
||||
@ -68,16 +68,6 @@ const struct ssh_digest digests[SSH_DIGEST_MAX] = {
|
||||
(md_update_fn *) MD5Update,
|
||||
(md_final_fn *) MD5Final
|
||||
},
|
||||
{
|
||||
SSH_DIGEST_RIPEMD160,
|
||||
"RIPEMD160",
|
||||
RMD160_BLOCK_LENGTH,
|
||||
RMD160_DIGEST_LENGTH,
|
||||
sizeof(RMD160_CTX),
|
||||
(md_init_fn *) RMD160Init,
|
||||
(md_update_fn *) RMD160Update,
|
||||
(md_final_fn *) RMD160Final
|
||||
},
|
||||
{
|
||||
SSH_DIGEST_SHA1,
|
||||
"SHA1",
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: digest-openssl.c,v 1.6 2017/03/10 02:59:51 dtucker Exp $ */
|
||||
/* $OpenBSD: digest-openssl.c,v 1.7 2017/05/08 22:57:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
|
||||
*
|
||||
@ -56,7 +56,6 @@ struct ssh_digest {
|
||||
/* NB. Indexed directly by algorithm number */
|
||||
const struct ssh_digest digests[] = {
|
||||
{ SSH_DIGEST_MD5, "MD5", 16, EVP_md5 },
|
||||
{ SSH_DIGEST_RIPEMD160, "RIPEMD160", 20, EVP_ripemd160 },
|
||||
{ SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 },
|
||||
{ SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 },
|
||||
{ SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 },
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: digest.h,v 1.7 2014/12/21 22:27:56 djm Exp $ */
|
||||
/* $OpenBSD: digest.h,v 1.8 2017/05/08 22:57:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
|
||||
*
|
||||
@ -23,12 +23,11 @@
|
||||
|
||||
/* Digest algorithms */
|
||||
#define SSH_DIGEST_MD5 0
|
||||
#define SSH_DIGEST_RIPEMD160 1
|
||||
#define SSH_DIGEST_SHA1 2
|
||||
#define SSH_DIGEST_SHA256 3
|
||||
#define SSH_DIGEST_SHA384 4
|
||||
#define SSH_DIGEST_SHA512 5
|
||||
#define SSH_DIGEST_MAX 6
|
||||
#define SSH_DIGEST_SHA1 1
|
||||
#define SSH_DIGEST_SHA256 2
|
||||
#define SSH_DIGEST_SHA384 3
|
||||
#define SSH_DIGEST_SHA512 4
|
||||
#define SSH_DIGEST_MAX 5
|
||||
|
||||
struct sshbuf;
|
||||
struct ssh_digest_ctx;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: dispatch.c,v 1.27 2015/05/01 07:10:01 djm Exp $ */
|
||||
/* $OpenBSD: dispatch.c,v 1.31 2017/05/31 07:00:13 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -30,7 +30,6 @@
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "ssh1.h"
|
||||
#include "ssh2.h"
|
||||
#include "log.h"
|
||||
#include "dispatch.h"
|
||||
@ -39,14 +38,11 @@
|
||||
#include "ssherr.h"
|
||||
|
||||
int
|
||||
dispatch_protocol_error(int type, u_int32_t seq, void *ctx)
|
||||
dispatch_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
int r;
|
||||
|
||||
logit("dispatch_protocol_error: type %d seq %u", type, seq);
|
||||
if (!compat20)
|
||||
fatal("protocol error");
|
||||
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
|
||||
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
|
||||
(r = sshpkt_send(ssh)) != 0 ||
|
||||
@ -56,7 +52,7 @@ dispatch_protocol_error(int type, u_int32_t seq, void *ctx)
|
||||
}
|
||||
|
||||
int
|
||||
dispatch_protocol_ignore(int type, u_int32_t seq, void *ssh)
|
||||
dispatch_protocol_ignore(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
logit("dispatch_protocol_ignore: type %d seq %u", type, seq);
|
||||
return 0;
|
||||
@ -89,8 +85,7 @@ ssh_dispatch_set(struct ssh *ssh, int type, dispatch_fn *fn)
|
||||
}
|
||||
|
||||
int
|
||||
ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done,
|
||||
void *ctxt)
|
||||
ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done)
|
||||
{
|
||||
int r;
|
||||
u_char type;
|
||||
@ -115,8 +110,7 @@ ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done,
|
||||
ssh->dispatch_skip_packets--;
|
||||
continue;
|
||||
}
|
||||
/* XXX 'ssh' will replace 'ctxt' later */
|
||||
r = (*ssh->dispatch[type])(type, seqnr, ctxt);
|
||||
r = (*ssh->dispatch[type])(type, seqnr, ssh);
|
||||
if (r != 0)
|
||||
return r;
|
||||
} else {
|
||||
@ -132,11 +126,10 @@ ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done,
|
||||
}
|
||||
|
||||
void
|
||||
ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done,
|
||||
void *ctxt)
|
||||
ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = ssh_dispatch_run(ssh, mode, done, ctxt)) != 0)
|
||||
if ((r = ssh_dispatch_run(ssh, mode, done)) != 0)
|
||||
sshpkt_fatal(ssh, __func__, r);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: dispatch.h,v 1.12 2015/01/19 20:07:45 markus Exp $ */
|
||||
/* $OpenBSD: dispatch.h,v 1.14 2017/05/31 07:00:13 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
@ -36,15 +36,15 @@ enum {
|
||||
|
||||
struct ssh;
|
||||
|
||||
typedef int dispatch_fn(int, u_int32_t, void *);
|
||||
typedef int dispatch_fn(int, u_int32_t, struct ssh *);
|
||||
|
||||
int dispatch_protocol_error(int, u_int32_t, void *);
|
||||
int dispatch_protocol_ignore(int, u_int32_t, void *);
|
||||
int dispatch_protocol_error(int, u_int32_t, struct ssh *);
|
||||
int dispatch_protocol_ignore(int, u_int32_t, struct ssh *);
|
||||
void ssh_dispatch_init(struct ssh *, dispatch_fn *);
|
||||
void ssh_dispatch_set(struct ssh *, int, dispatch_fn *);
|
||||
void ssh_dispatch_range(struct ssh *, u_int, u_int, dispatch_fn *);
|
||||
int ssh_dispatch_run(struct ssh *, int, volatile sig_atomic_t *, void *);
|
||||
void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *, void *);
|
||||
int ssh_dispatch_run(struct ssh *, int, volatile sig_atomic_t *);
|
||||
void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *);
|
||||
|
||||
#define dispatch_init(dflt) \
|
||||
ssh_dispatch_init(active_state, (dflt))
|
||||
@ -52,7 +52,5 @@ void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *, void *);
|
||||
ssh_dispatch_range(active_state, (from), (to), (fn))
|
||||
#define dispatch_set(type, fn) \
|
||||
ssh_dispatch_set(active_state, (type), (fn))
|
||||
#define dispatch_run(mode, done, ctxt) \
|
||||
ssh_dispatch_run_fatal(active_state, (mode), (done), (ctxt))
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: dns.c,v 1.35 2015/08/20 22:32:42 deraadt Exp $ */
|
||||
/* $OpenBSD: dns.c,v 1.37 2017/09/14 04:32:21 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: dns.h,v 1.15 2015/05/08 06:45:13 djm Exp $ */
|
||||
/* $OpenBSD: dns.h,v 1.17 2017/09/14 04:32:21 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
|
||||
|
84
crypto/openssh/freebsd-namespace.sh
Executable file
84
crypto/openssh/freebsd-namespace.sh
Executable file
@ -0,0 +1,84 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Namespace munging inspired by an equivalent hack in NetBSD's tree: add
|
||||
# the "Fssh_" prefix to every symbol in libssh which doesn't already have
|
||||
# it. This prevents collisions between symbols in libssh and symbols in
|
||||
# other libraries or applications which link with libssh, either directly
|
||||
# or indirectly (e.g. through PAM loading pam_ssh).
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
eval "unset $(env | sed -nE 's/^(LC_[A-Z]+)=.*$/\1/p')"
|
||||
export LANG=C
|
||||
|
||||
error() {
|
||||
echo "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Locate the source directories
|
||||
self=$(realpath ${0})
|
||||
srcdir=${self%/*}
|
||||
header=${srcdir}/ssh_namespace.h
|
||||
top_srcdir=${srcdir%/crypto/openssh}
|
||||
libssh_srcdir=${top_srcdir}/secure/lib/libssh
|
||||
|
||||
if [ ! -d ${srcdir} -o \
|
||||
! -f ${header} -o \
|
||||
! -d ${libssh_srcdir} -o \
|
||||
! -f ${libssh_srcdir}/Makefile ] ; then
|
||||
error "Where is the libssh Makefile?"
|
||||
fi
|
||||
|
||||
ncpu=$(sysctl -n hw.ncpu)
|
||||
ssh_make() {
|
||||
make -C${libssh_srcdir} -j$((ncpu + 1)) "$@"
|
||||
}
|
||||
|
||||
# Clear out, recreate and locate the libssh build directory
|
||||
ssh_make cleandir
|
||||
ssh_make cleandir
|
||||
ssh_make obj
|
||||
libssh_builddir=$(realpath $(ssh_make -V.OBJDIR))
|
||||
libssh=libprivatessh.a
|
||||
|
||||
# Clear the existing header
|
||||
cat >${header} <<EOF
|
||||
/*
|
||||
* This file was machine-generated. Do not edit manually.
|
||||
* Run crypto/openssh/freebsd-namespace.sh to regenerate.
|
||||
*/
|
||||
EOF
|
||||
|
||||
# Build libssh
|
||||
ssh_make depend
|
||||
ssh_make ${libssh}
|
||||
if [ ! -f ${libssh_builddir}/${libssh} ] ; then
|
||||
error "Where is ${libssh}?"
|
||||
fi
|
||||
|
||||
# Extract symbols
|
||||
nm ${libssh_builddir}/${libssh} | awk '
|
||||
/^[0-9a-z]+ [Tt] [A-Za-z_][0-9A-Za-z_]*$/ && $3 !~ /^Fssh_/ {
|
||||
printf("#define %-39s Fssh_%s\n", $3, $3)
|
||||
}
|
||||
' | unexpand -a | sort -u >>${header}
|
||||
|
||||
# Clean and rebuild the library
|
||||
ssh_make clean
|
||||
ssh_make ${libssh}
|
||||
|
||||
# Double-check
|
||||
nm ${libssh_builddir}/${libssh} | awk '
|
||||
/^[0-9a-z]+ [Tt] [A-Za-z_][0-9A-Za-z_]*$/ && $3 !~ /^Fssh_/ {
|
||||
printf("ERROR: %s was not renamed!\n", $3);
|
||||
err++;
|
||||
}
|
||||
END {
|
||||
if (err > 0)
|
||||
exit(1);
|
||||
}
|
||||
'
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: gss-serv.c,v 1.29 2015/05/22 03:50:02 djm Exp $ */
|
||||
/* $OpenBSD: gss-serv.c,v 1.30 2017/06/24 06:34:38 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
|
||||
@ -393,4 +393,13 @@ ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
|
||||
return (ctx->major);
|
||||
}
|
||||
|
||||
/* Privileged */
|
||||
const char *ssh_gssapi_displayname(void)
|
||||
{
|
||||
if (gssapi_client.displayname.length == 0 ||
|
||||
gssapi_client.displayname.value == NULL)
|
||||
return NULL;
|
||||
return (char *)gssapi_client.displayname.value;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: hostfile.c,v 1.68 2017/03/10 04:26:06 djm Exp $ */
|
||||
/* $OpenBSD: hostfile.c,v 1.71 2017/05/31 09:15:42 deraadt Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -251,7 +251,7 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx)
|
||||
l->marker == MRK_NONE ? "" :
|
||||
(l->marker == MRK_CA ? "ca " : "revoked "),
|
||||
sshkey_type(l->key), l->path, l->linenum);
|
||||
if ((tmp = reallocarray(hostkeys->entries,
|
||||
if ((tmp = recallocarray(hostkeys->entries, hostkeys->num_entries,
|
||||
hostkeys->num_entries + 1, sizeof(*hostkeys->entries))) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
hostkeys->entries = tmp;
|
||||
@ -346,16 +346,11 @@ check_hostkeys_by_key_or_type(struct hostkeys *hostkeys,
|
||||
HostStatus end_return = HOST_NEW;
|
||||
int want_cert = sshkey_is_cert(k);
|
||||
HostkeyMarker want_marker = want_cert ? MRK_CA : MRK_NONE;
|
||||
int proto = (k ? k->type : keytype) == KEY_RSA1 ? 1 : 2;
|
||||
|
||||
if (found != NULL)
|
||||
*found = NULL;
|
||||
|
||||
for (i = 0; i < hostkeys->num_entries; i++) {
|
||||
if (proto == 1 && hostkeys->entries[i].key->type != KEY_RSA1)
|
||||
continue;
|
||||
if (proto == 2 && hostkeys->entries[i].key->type == KEY_RSA1)
|
||||
continue;
|
||||
if (hostkeys->entries[i].marker != want_marker)
|
||||
continue;
|
||||
if (k == NULL) {
|
||||
@ -490,13 +485,6 @@ host_delete(struct hostkey_foreach_line *l, void *_ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX might need a knob for this later */
|
||||
/* Don't remove RSA1 keys */
|
||||
if (l->key->type == KEY_RSA1) {
|
||||
fprintf(ctx->out, "%s\n", l->line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this line contains one of the keys that we will be
|
||||
* adding later, then don't change it and mark the key for
|
||||
@ -789,20 +777,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
|
||||
break;
|
||||
}
|
||||
if (!hostfile_read_key(&cp, &kbits, lineinfo.key)) {
|
||||
#ifdef WITH_SSH1
|
||||
sshkey_free(lineinfo.key);
|
||||
lineinfo.key = sshkey_new(KEY_RSA1);
|
||||
if (lineinfo.key == NULL) {
|
||||
error("%s: sshkey_new fail", __func__);
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
break;
|
||||
}
|
||||
if (!hostfile_read_key(&cp, &kbits,
|
||||
lineinfo.key))
|
||||
goto bad;
|
||||
#else
|
||||
goto bad;
|
||||
#endif
|
||||
}
|
||||
lineinfo.keytype = lineinfo.key->type;
|
||||
lineinfo.comment = cp;
|
||||
@ -817,12 +792,12 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
|
||||
lineinfo.keytype = sshkey_type_from_name(ktype);
|
||||
|
||||
/*
|
||||
* Assume RSA1 if the first component is a short
|
||||
* Assume legacy RSA1 if the first component is a short
|
||||
* decimal number.
|
||||
*/
|
||||
if (lineinfo.keytype == KEY_UNSPEC && l < 8 &&
|
||||
strspn(ktype, "0123456789") == l)
|
||||
lineinfo.keytype = KEY_RSA1;
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* Check that something other than whitespace follows
|
||||
|
@ -93,6 +93,9 @@
|
||||
#ifdef HAVE_SYS_SYSMACROS_H
|
||||
# include <sys/sysmacros.h> /* For MIN, MAX, etc */
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h> /* for timespeccmp if present */
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h> /* for MAP_ANONYMOUS */
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kex.c,v 1.131 2017/03/15 07:07:39 markus Exp $ */
|
||||
/* $OpenBSD: kex.c,v 1.134 2017/06/13 12:13:59 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -54,17 +54,9 @@
|
||||
#include "sshbuf.h"
|
||||
#include "digest.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
||||
# if defined(HAVE_EVP_SHA256)
|
||||
# define evp_ssh_sha256 EVP_sha256
|
||||
# else
|
||||
extern const EVP_MD *evp_ssh_sha256(void);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* prototype */
|
||||
static int kex_choose_conf(struct ssh *);
|
||||
static int kex_input_newkeys(int, u_int32_t, void *);
|
||||
static int kex_input_newkeys(int, u_int32_t, struct ssh *);
|
||||
|
||||
static const char *proposal_names[PROPOSAL_MAX] = {
|
||||
"KEX algorithms",
|
||||
@ -323,9 +315,8 @@ kex_prop_free(char **proposal)
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
kex_protocol_error(int type, u_int32_t seq, void *ctxt)
|
||||
kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
int r;
|
||||
|
||||
error("kex protocol error: type %d seq %u", type, seq);
|
||||
@ -383,12 +374,13 @@ kex_send_newkeys(struct ssh *ssh)
|
||||
}
|
||||
|
||||
int
|
||||
kex_input_ext_info(int type, u_int32_t seq, void *ctxt)
|
||||
kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
u_int32_t i, ninfo;
|
||||
char *name, *val, *found;
|
||||
char *name, *found;
|
||||
u_char *val;
|
||||
size_t vlen;
|
||||
int r;
|
||||
|
||||
debug("SSH2_MSG_EXT_INFO received");
|
||||
@ -398,12 +390,17 @@ kex_input_ext_info(int type, u_int32_t seq, void *ctxt)
|
||||
for (i = 0; i < ninfo; i++) {
|
||||
if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
|
||||
return r;
|
||||
if ((r = sshpkt_get_cstring(ssh, &val, NULL)) != 0) {
|
||||
if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) {
|
||||
free(name);
|
||||
return r;
|
||||
}
|
||||
debug("%s: %s=<%s>", __func__, name, val);
|
||||
if (strcmp(name, "server-sig-algs") == 0) {
|
||||
/* Ensure no \0 lurking in value */
|
||||
if (memchr(val, '\0', vlen) != NULL) {
|
||||
error("%s: nul byte in %s", __func__, name);
|
||||
return SSH_ERR_INVALID_FORMAT;
|
||||
}
|
||||
debug("%s: %s=<%s>", __func__, name, val);
|
||||
found = match_list("rsa-sha2-256", val, NULL);
|
||||
if (found) {
|
||||
kex->rsa_sha2 = 256;
|
||||
@ -414,7 +411,8 @@ kex_input_ext_info(int type, u_int32_t seq, void *ctxt)
|
||||
kex->rsa_sha2 = 512;
|
||||
free(found);
|
||||
}
|
||||
}
|
||||
} else
|
||||
debug("%s: %s (unrecognised)", __func__, name);
|
||||
free(name);
|
||||
free(val);
|
||||
}
|
||||
@ -422,9 +420,8 @@ kex_input_ext_info(int type, u_int32_t seq, void *ctxt)
|
||||
}
|
||||
|
||||
static int
|
||||
kex_input_newkeys(int type, u_int32_t seq, void *ctxt)
|
||||
kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
int r;
|
||||
|
||||
@ -475,9 +472,8 @@ kex_send_kexinit(struct ssh *ssh)
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
|
||||
kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
const u_char *ptr;
|
||||
u_int i;
|
||||
@ -988,47 +984,6 @@ kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
int
|
||||
derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
|
||||
u_int8_t cookie[8], u_int8_t id[16])
|
||||
{
|
||||
u_int8_t hbuf[2048], sbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH];
|
||||
struct ssh_digest_ctx *hashctx = NULL;
|
||||
size_t hlen, slen;
|
||||
int r;
|
||||
|
||||
hlen = BN_num_bytes(host_modulus);
|
||||
slen = BN_num_bytes(server_modulus);
|
||||
if (hlen < (512 / 8) || (u_int)hlen > sizeof(hbuf) ||
|
||||
slen < (512 / 8) || (u_int)slen > sizeof(sbuf))
|
||||
return SSH_ERR_KEY_BITS_MISMATCH;
|
||||
if (BN_bn2bin(host_modulus, hbuf) <= 0 ||
|
||||
BN_bn2bin(server_modulus, sbuf) <= 0) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (ssh_digest_update(hashctx, hbuf, hlen) != 0 ||
|
||||
ssh_digest_update(hashctx, sbuf, slen) != 0 ||
|
||||
ssh_digest_update(hashctx, cookie, 8) != 0 ||
|
||||
ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5));
|
||||
r = 0;
|
||||
out:
|
||||
ssh_digest_free(hashctx);
|
||||
explicit_bzero(hbuf, sizeof(hbuf));
|
||||
explicit_bzero(sbuf, sizeof(sbuf));
|
||||
explicit_bzero(obuf, sizeof(obuf));
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
|
||||
void
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kex.h,v 1.81 2016/09/28 21:44:52 djm Exp $ */
|
||||
/* $OpenBSD: kex.h,v 1.83 2017/05/30 14:23:52 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
@ -181,8 +181,8 @@ int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]);
|
||||
void kex_prop_free(char **);
|
||||
|
||||
int kex_send_kexinit(struct ssh *);
|
||||
int kex_input_kexinit(int, u_int32_t, void *);
|
||||
int kex_input_ext_info(int, u_int32_t, void *);
|
||||
int kex_input_kexinit(int, u_int32_t, struct ssh *);
|
||||
int kex_input_ext_info(int, u_int32_t, struct ssh *);
|
||||
int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *);
|
||||
int kex_derive_keys_bn(struct ssh *, u_char *, u_int, const BIGNUM *);
|
||||
int kex_send_newkeys(struct ssh *);
|
||||
@ -225,9 +225,6 @@ int kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
|
||||
__attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
|
||||
__attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
|
||||
|
||||
int
|
||||
derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]);
|
||||
|
||||
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
|
||||
void dump_digest(char *, u_char *, int);
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kexc25519c.c,v 1.7 2015/01/26 06:10:03 djm Exp $ */
|
||||
/* $OpenBSD: kexc25519c.c,v 1.8 2017/05/31 04:17:12 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||
@ -44,7 +44,7 @@
|
||||
#include "ssherr.h"
|
||||
|
||||
static int
|
||||
input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt);
|
||||
input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh);
|
||||
|
||||
int
|
||||
kexc25519_client(struct ssh *ssh)
|
||||
@ -69,9 +69,8 @@ kexc25519_client(struct ssh *ssh)
|
||||
}
|
||||
|
||||
static int
|
||||
input_kex_c25519_reply(int type, u_int32_t seq, void *ctxt)
|
||||
input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
struct sshkey *server_host_key = NULL;
|
||||
struct sshbuf *shared_secret = NULL;
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "sshbuf.h"
|
||||
#include "ssherr.h"
|
||||
|
||||
static int input_kex_c25519_init(int, u_int32_t, void *);
|
||||
static int input_kex_c25519_init(int, u_int32_t, struct ssh *);
|
||||
|
||||
int
|
||||
kexc25519_server(struct ssh *ssh)
|
||||
@ -52,9 +52,8 @@ kexc25519_server(struct ssh *ssh)
|
||||
}
|
||||
|
||||
static int
|
||||
input_kex_c25519_init(int type, u_int32_t seq, void *ctxt)
|
||||
input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
struct sshkey *server_host_private, *server_host_public;
|
||||
struct sshbuf *shared_secret = NULL;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kexdhc.c,v 1.19 2016/05/02 10:26:04 djm Exp $ */
|
||||
/* $OpenBSD: kexdhc.c,v 1.20 2017/05/30 14:23:52 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -49,7 +49,7 @@
|
||||
#include "ssherr.h"
|
||||
#include "sshbuf.h"
|
||||
|
||||
static int input_kex_dh(int, u_int32_t, void *);
|
||||
static int input_kex_dh(int, u_int32_t, struct ssh *);
|
||||
|
||||
int
|
||||
kexdh_client(struct ssh *ssh)
|
||||
@ -100,9 +100,8 @@ kexdh_client(struct ssh *ssh)
|
||||
}
|
||||
|
||||
static int
|
||||
input_kex_dh(int type, u_int32_t seq, void *ctxt)
|
||||
input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
|
||||
struct sshkey *server_host_key = NULL;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kexdhs.c,v 1.24 2016/05/02 10:26:04 djm Exp $ */
|
||||
/* $OpenBSD: kexdhs.c,v 1.25 2017/05/30 14:23:52 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -49,7 +49,7 @@
|
||||
#include "ssherr.h"
|
||||
#include "sshbuf.h"
|
||||
|
||||
static int input_kex_dh_init(int, u_int32_t, void *);
|
||||
static int input_kex_dh_init(int, u_int32_t, struct ssh *);
|
||||
|
||||
int
|
||||
kexdh_server(struct ssh *ssh)
|
||||
@ -91,9 +91,8 @@ kexdh_server(struct ssh *ssh)
|
||||
}
|
||||
|
||||
int
|
||||
input_kex_dh_init(int type, u_int32_t seq, void *ctxt)
|
||||
input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
|
||||
struct sshkey *server_host_public, *server_host_private;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kexecdhc.c,v 1.10 2015/01/26 06:10:03 djm Exp $ */
|
||||
/* $OpenBSD: kexecdhc.c,v 1.11 2017/05/30 14:23:52 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||
@ -49,7 +49,7 @@
|
||||
#include "ssherr.h"
|
||||
#include "sshbuf.h"
|
||||
|
||||
static int input_kex_ecdh_reply(int, u_int32_t, void *);
|
||||
static int input_kex_ecdh_reply(int, u_int32_t, struct ssh *);
|
||||
|
||||
int
|
||||
kexecdh_client(struct ssh *ssh)
|
||||
@ -95,9 +95,8 @@ kexecdh_client(struct ssh *ssh)
|
||||
}
|
||||
|
||||
static int
|
||||
input_kex_ecdh_reply(int type, u_int32_t seq, void *ctxt)
|
||||
input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
const EC_GROUP *group;
|
||||
EC_POINT *server_public = NULL;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kexecdhs.c,v 1.15 2015/12/04 16:41:28 markus Exp $ */
|
||||
/* $OpenBSD: kexecdhs.c,v 1.16 2017/05/30 14:23:52 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||
@ -47,7 +47,7 @@
|
||||
#include "ssherr.h"
|
||||
#include "sshbuf.h"
|
||||
|
||||
static int input_kex_ecdh_init(int, u_int32_t, void *);
|
||||
static int input_kex_ecdh_init(int, u_int32_t, struct ssh *);
|
||||
|
||||
int
|
||||
kexecdh_server(struct ssh *ssh)
|
||||
@ -58,9 +58,8 @@ kexecdh_server(struct ssh *ssh)
|
||||
}
|
||||
|
||||
static int
|
||||
input_kex_ecdh_init(int type, u_int32_t seq, void *ctxt)
|
||||
input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
EC_POINT *client_public;
|
||||
EC_KEY *server_key = NULL;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kexgexc.c,v 1.23 2016/09/12 01:22:38 deraadt Exp $ */
|
||||
/* $OpenBSD: kexgexc.c,v 1.25 2017/05/30 14:23:52 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
@ -51,8 +51,8 @@
|
||||
#include "sshbuf.h"
|
||||
#include "misc.h"
|
||||
|
||||
static int input_kex_dh_gex_group(int, u_int32_t, void *);
|
||||
static int input_kex_dh_gex_reply(int, u_int32_t, void *);
|
||||
static int input_kex_dh_gex_group(int, u_int32_t, struct ssh *);
|
||||
static int input_kex_dh_gex_reply(int, u_int32_t, struct ssh *);
|
||||
|
||||
int
|
||||
kexgex_client(struct ssh *ssh)
|
||||
@ -89,9 +89,8 @@ kexgex_client(struct ssh *ssh)
|
||||
}
|
||||
|
||||
static int
|
||||
input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt)
|
||||
input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
BIGNUM *p = NULL, *g = NULL;
|
||||
int r, bits;
|
||||
@ -143,9 +142,8 @@ input_kex_dh_gex_group(int type, u_int32_t seq, void *ctxt)
|
||||
}
|
||||
|
||||
static int
|
||||
input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt)
|
||||
input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
|
||||
struct sshkey *server_host_key = NULL;
|
||||
@ -165,10 +163,6 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, void *ctxt)
|
||||
(r = sshkey_from_blob(server_host_key_blob, sbloblen,
|
||||
&server_host_key)) != 0)
|
||||
goto out;
|
||||
if (server_host_key->type != kex->hostkey_type) {
|
||||
r = SSH_ERR_KEY_TYPE_MISMATCH;
|
||||
goto out;
|
||||
}
|
||||
if (server_host_key->type != kex->hostkey_type ||
|
||||
(kex->hostkey_type == KEY_ECDSA &&
|
||||
server_host_key->ecdsa_nid != kex->hostkey_nid)) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kexgexs.c,v 1.30 2016/09/12 01:22:38 deraadt Exp $ */
|
||||
/* $OpenBSD: kexgexs.c,v 1.31 2017/05/30 14:23:52 markus Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
@ -54,8 +54,8 @@
|
||||
#include "sshbuf.h"
|
||||
#include "misc.h"
|
||||
|
||||
static int input_kex_dh_gex_request(int, u_int32_t, void *);
|
||||
static int input_kex_dh_gex_init(int, u_int32_t, void *);
|
||||
static int input_kex_dh_gex_request(int, u_int32_t, struct ssh *);
|
||||
static int input_kex_dh_gex_init(int, u_int32_t, struct ssh *);
|
||||
|
||||
int
|
||||
kexgex_server(struct ssh *ssh)
|
||||
@ -67,9 +67,8 @@ kexgex_server(struct ssh *ssh)
|
||||
}
|
||||
|
||||
static int
|
||||
input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt)
|
||||
input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
int r;
|
||||
u_int min = 0, max = 0, nbits = 0;
|
||||
@ -120,9 +119,8 @@ input_kex_dh_gex_request(int type, u_int32_t seq, void *ctxt)
|
||||
}
|
||||
|
||||
static int
|
||||
input_kex_dh_gex_init(int type, u_int32_t seq, void *ctxt)
|
||||
input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
|
||||
{
|
||||
struct ssh *ssh = ctxt;
|
||||
struct kex *kex = ssh->kex;
|
||||
BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
|
||||
struct sshkey *server_host_public, *server_host_private;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: key.c,v 1.130 2016/05/02 09:36:42 djm Exp $ */
|
||||
/* $OpenBSD: key.c,v 1.131 2017/05/30 14:16:41 markus Exp $ */
|
||||
/*
|
||||
* placed in the public domain
|
||||
*/
|
||||
@ -20,68 +20,6 @@
|
||||
#include "log.h"
|
||||
#include "authfile.h"
|
||||
|
||||
void
|
||||
key_add_private(Key *k)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_add_private(k)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
Key *
|
||||
key_new_private(int type)
|
||||
{
|
||||
Key *ret = NULL;
|
||||
|
||||
if ((ret = sshkey_new_private(type)) == NULL)
|
||||
fatal("%s: failed", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
key_read(Key *ret, char **cpp)
|
||||
{
|
||||
return sshkey_read(ret, cpp) == 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
int
|
||||
key_write(const Key *key, FILE *f)
|
||||
{
|
||||
return sshkey_write(key, f) == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
Key *
|
||||
key_generate(int type, u_int bits)
|
||||
{
|
||||
int r;
|
||||
Key *ret = NULL;
|
||||
|
||||
if ((r = sshkey_generate(type, bits, &ret)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
key_cert_copy(const Key *from_key, Key *to_key)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_cert_copy(from_key, to_key)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
Key *
|
||||
key_from_private(const Key *k)
|
||||
{
|
||||
int r;
|
||||
Key *ret = NULL;
|
||||
|
||||
if ((r = sshkey_from_private(k, &ret)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
fatal_on_fatal_errors(int r, const char *func, int extra_fatal)
|
||||
{
|
||||
@ -183,19 +121,6 @@ key_demote(const Key *k)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
key_to_certified(Key *k)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_to_certified(k)) != 0) {
|
||||
fatal_on_fatal_errors(r, __func__, 0);
|
||||
error("%s: %s", __func__, ssh_err(r));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
key_drop_cert(Key *k)
|
||||
{
|
||||
@ -209,19 +134,6 @@ key_drop_cert(Key *k)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
key_certify(Key *k, Key *ca)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_certify(k, ca, NULL)) != 0) {
|
||||
fatal_on_fatal_errors(r, __func__, 0);
|
||||
error("%s: %s", __func__, ssh_err(r));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
key_cert_check_authority(const Key *k, int want_host, int require_principal,
|
||||
const char *name, const char **reason)
|
||||
@ -237,88 +149,8 @@ key_cert_check_authority(const Key *k, int want_host, int require_principal,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
|
||||
int
|
||||
key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_ec_validate_public(group, public)) != 0) {
|
||||
fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
|
||||
error("%s: %s", __func__, ssh_err(r));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
key_ec_validate_private(const EC_KEY *key)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_ec_validate_private(key)) != 0) {
|
||||
fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
|
||||
error("%s: %s", __func__, ssh_err(r));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
||||
void
|
||||
key_private_serialize(const Key *key, struct sshbuf *b)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_private_serialize(key, b)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
Key *
|
||||
key_private_deserialize(struct sshbuf *blob)
|
||||
{
|
||||
int r;
|
||||
Key *ret = NULL;
|
||||
|
||||
if ((r = sshkey_private_deserialize(blob, &ret)) != 0) {
|
||||
fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
|
||||
error("%s: %s", __func__, ssh_err(r));
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* authfile.c */
|
||||
|
||||
int
|
||||
key_save_private(Key *key, const char *filename, const char *passphrase,
|
||||
const char *comment, int force_new_format, const char *new_format_cipher,
|
||||
int new_format_rounds)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_save_private(key, filename, passphrase, comment,
|
||||
force_new_format, new_format_cipher, new_format_rounds)) != 0) {
|
||||
fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
|
||||
error("%s: %s", __func__, ssh_err(r));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
key_load_file(int fd, const char *filename, struct sshbuf *blob)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_load_file(fd, blob)) != 0) {
|
||||
fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
|
||||
error("%s: %s", __func__, ssh_err(r));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Key *
|
||||
key_load_cert(const char *filename)
|
||||
{
|
||||
@ -417,10 +249,3 @@ key_load_private_type(int type, const char *filename, const char *passphrase,
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
key_perm_ok(int fd, const char *filename)
|
||||
{
|
||||
return sshkey_perm_ok(fd, filename) == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: key.h,v 1.50 2016/09/12 23:31:27 djm Exp $ */
|
||||
/* $OpenBSD: key.h,v 1.51 2017/05/30 14:16:41 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
@ -35,51 +35,24 @@ typedef struct sshkey Key;
|
||||
#define fp_rep sshkey_fp_rep
|
||||
|
||||
#ifndef SSH_KEY_NO_DEFINE
|
||||
#define key_new sshkey_new
|
||||
#define key_free sshkey_free
|
||||
#define key_equal_public sshkey_equal_public
|
||||
#define key_equal sshkey_equal
|
||||
#define key_type sshkey_type
|
||||
#define key_cert_type sshkey_cert_type
|
||||
#define key_ssh_name sshkey_ssh_name
|
||||
#define key_ssh_name_plain sshkey_ssh_name_plain
|
||||
#define key_type_from_name sshkey_type_from_name
|
||||
#define key_ecdsa_nid_from_name sshkey_ecdsa_nid_from_name
|
||||
#define key_type_is_cert sshkey_type_is_cert
|
||||
#define key_size sshkey_size
|
||||
#define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid
|
||||
#define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid
|
||||
#define key_is_cert sshkey_is_cert
|
||||
#define key_type_plain sshkey_type_plain
|
||||
#define key_curve_name_to_nid sshkey_curve_name_to_nid
|
||||
#define key_curve_nid_to_bits sshkey_curve_nid_to_bits
|
||||
#define key_curve_nid_to_name sshkey_curve_nid_to_name
|
||||
#define key_ec_nid_to_hash_alg sshkey_ec_nid_to_hash_alg
|
||||
#define key_dump_ec_point sshkey_dump_ec_point
|
||||
#define key_dump_ec_key sshkey_dump_ec_key
|
||||
#endif
|
||||
|
||||
void key_add_private(Key *);
|
||||
Key *key_new_private(int);
|
||||
void key_free(Key *);
|
||||
Key *key_demote(const Key *);
|
||||
int key_write(const Key *, FILE *);
|
||||
int key_read(Key *, char **);
|
||||
|
||||
Key *key_generate(int, u_int);
|
||||
Key *key_from_private(const Key *);
|
||||
int key_to_certified(Key *);
|
||||
int key_drop_cert(Key *);
|
||||
int key_certify(Key *, Key *);
|
||||
void key_cert_copy(const Key *, Key *);
|
||||
int key_cert_check_authority(const Key *, int, int, const char *,
|
||||
const char **);
|
||||
|
||||
#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
|
||||
int key_ec_validate_public(const EC_GROUP *, const EC_POINT *);
|
||||
int key_ec_validate_private(const EC_KEY *);
|
||||
#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
|
||||
|
||||
Key *key_from_blob(const u_char *, u_int);
|
||||
int key_to_blob(const Key *, u_char **, u_int *);
|
||||
|
||||
@ -87,18 +60,11 @@ int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int,
|
||||
const char *);
|
||||
int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
|
||||
|
||||
void key_private_serialize(const Key *, struct sshbuf *);
|
||||
Key *key_private_deserialize(struct sshbuf *);
|
||||
|
||||
/* authfile.c */
|
||||
int key_save_private(Key *, const char *, const char *, const char *,
|
||||
int, const char *, int);
|
||||
int key_load_file(int, const char *, struct sshbuf *);
|
||||
Key *key_load_cert(const char *);
|
||||
Key *key_load_public(const char *, char **);
|
||||
Key *key_load_private(const char *, const char *, char **);
|
||||
Key *key_load_private_cert(int, const char *, const char *, int *);
|
||||
Key *key_load_private_type(int, const char *, const char *, char **, int *);
|
||||
int key_perm_ok(int, const char *);
|
||||
|
||||
#endif
|
||||
|
@ -14,7 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $OpenBSD: krl.c,v 1.39 2017/03/10 07:18:32 dtucker Exp $ */
|
||||
/* $OpenBSD: krl.c,v 1.40 2017/05/31 09:15:42 deraadt Exp $ */
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
@ -1026,7 +1026,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
|
||||
}
|
||||
}
|
||||
/* Record keys used to sign the KRL */
|
||||
tmp_ca_used = reallocarray(ca_used, nca_used + 1,
|
||||
tmp_ca_used = recallocarray(ca_used, nca_used, nca_used + 1,
|
||||
sizeof(*ca_used));
|
||||
if (tmp_ca_used == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: log.c,v 1.49 2017/03/10 03:15:58 djm Exp $ */
|
||||
/* $OpenBSD: log.c,v 1.50 2017/05/17 01:24:17 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -256,18 +256,7 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
|
||||
|
||||
argv0 = av0;
|
||||
|
||||
switch (level) {
|
||||
case SYSLOG_LEVEL_QUIET:
|
||||
case SYSLOG_LEVEL_FATAL:
|
||||
case SYSLOG_LEVEL_ERROR:
|
||||
case SYSLOG_LEVEL_INFO:
|
||||
case SYSLOG_LEVEL_VERBOSE:
|
||||
case SYSLOG_LEVEL_DEBUG1:
|
||||
case SYSLOG_LEVEL_DEBUG2:
|
||||
case SYSLOG_LEVEL_DEBUG3:
|
||||
log_level = level;
|
||||
break;
|
||||
default:
|
||||
if (log_change_level(level) != 0) {
|
||||
fprintf(stderr, "Unrecognized internal syslog level code %d\n",
|
||||
(int) level);
|
||||
exit(1);
|
||||
@ -340,13 +329,27 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
log_change_level(LogLevel new_log_level)
|
||||
{
|
||||
/* no-op if log_init has not been called */
|
||||
if (argv0 == NULL)
|
||||
return;
|
||||
log_init(argv0, new_log_level, log_facility, log_on_stderr);
|
||||
return 0;
|
||||
|
||||
switch (new_log_level) {
|
||||
case SYSLOG_LEVEL_QUIET:
|
||||
case SYSLOG_LEVEL_FATAL:
|
||||
case SYSLOG_LEVEL_ERROR:
|
||||
case SYSLOG_LEVEL_INFO:
|
||||
case SYSLOG_LEVEL_VERBOSE:
|
||||
case SYSLOG_LEVEL_DEBUG1:
|
||||
case SYSLOG_LEVEL_DEBUG2:
|
||||
case SYSLOG_LEVEL_DEBUG3:
|
||||
log_level = new_log_level;
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: log.h,v 1.21 2016/07/15 05:01:58 dtucker Exp $ */
|
||||
/* $OpenBSD: log.h,v 1.22 2017/05/17 01:24:17 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -49,7 +49,7 @@ typedef enum {
|
||||
typedef void (log_handler_fn)(LogLevel, const char *, void *);
|
||||
|
||||
void log_init(char *, LogLevel, SyslogFacility, int);
|
||||
void log_change_level(LogLevel);
|
||||
int log_change_level(LogLevel);
|
||||
int log_is_on_stderr(void);
|
||||
void log_redirect_stderr_to(const char *);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: mac.c,v 1.33 2016/07/08 03:44:42 djm Exp $ */
|
||||
/* $OpenBSD: mac.c,v 1.34 2017/05/08 22:57:38 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -64,10 +64,6 @@ static const struct macalg macs[] = {
|
||||
#endif
|
||||
{ "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 },
|
||||
{ "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 },
|
||||
#ifdef HAVE_EVP_RIPEMD160
|
||||
{ "hmac-ripemd160", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 },
|
||||
{ "hmac-ripemd160@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 },
|
||||
#endif
|
||||
{ "umac-64@openssh.com", SSH_UMAC, 0, 0, 128, 64, 0 },
|
||||
{ "umac-128@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 0 },
|
||||
|
||||
@ -80,9 +76,6 @@ static const struct macalg macs[] = {
|
||||
#endif
|
||||
{ "hmac-md5-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 1 },
|
||||
{ "hmac-md5-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 1 },
|
||||
#ifdef HAVE_EVP_RIPEMD160
|
||||
{ "hmac-ripemd160-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 1 },
|
||||
#endif
|
||||
{ "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 },
|
||||
{ "umac-128-etm@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 1 },
|
||||
|
||||
|
@ -1,86 +0,0 @@
|
||||
/* $OpenBSD: md-sha256.c,v 1.5 2006/08/03 03:34:42 deraadt Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2005 Damien Miller <djm@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* EVP wrapper for SHA256 */
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <openssl/opensslv.h>
|
||||
|
||||
#if !defined(HAVE_EVP_SHA256) && (OPENSSL_VERSION_NUMBER >= 0x00907000L)
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#ifdef HAVE_SHA256_UPDATE
|
||||
# ifdef HAVE_SHA2_H
|
||||
# include <sha2.h>
|
||||
# elif defined(HAVE_CRYPTO_SHA2_H)
|
||||
# include <crypto/sha2.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
const EVP_MD *evp_ssh_sha256(void);
|
||||
|
||||
static int
|
||||
ssh_sha256_init(EVP_MD_CTX *ctxt)
|
||||
{
|
||||
SHA256_Init(ctxt->md_data);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_sha256_update(EVP_MD_CTX *ctxt, const void *data, unsigned long len)
|
||||
{
|
||||
SHA256_Update(ctxt->md_data, data, len);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_sha256_final(EVP_MD_CTX *ctxt, unsigned char *digest)
|
||||
{
|
||||
SHA256_Final(digest, ctxt->md_data);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_sha256_cleanup(EVP_MD_CTX *ctxt)
|
||||
{
|
||||
memset(ctxt->md_data, 0, sizeof(SHA256_CTX));
|
||||
return (1);
|
||||
}
|
||||
|
||||
const EVP_MD *
|
||||
evp_ssh_sha256(void)
|
||||
{
|
||||
static EVP_MD ssh_sha256;
|
||||
|
||||
memset(&ssh_sha256, 0, sizeof(ssh_sha256));
|
||||
ssh_sha256.type = NID_undef;
|
||||
ssh_sha256.md_size = SHA256_DIGEST_LENGTH;
|
||||
ssh_sha256.init = ssh_sha256_init;
|
||||
ssh_sha256.update = ssh_sha256_update;
|
||||
ssh_sha256.final = ssh_sha256_final;
|
||||
ssh_sha256.cleanup = ssh_sha256_cleanup;
|
||||
ssh_sha256.block_size = SHA256_BLOCK_LENGTH;
|
||||
ssh_sha256.ctx_size = sizeof(SHA256_CTX);
|
||||
|
||||
return (&ssh_sha256);
|
||||
}
|
||||
|
||||
#endif /* !defined(HAVE_EVP_SHA256) && (OPENSSL_VERSION_NUMBER >= 0x00907000L) */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: misc.c,v 1.109 2017/03/14 00:55:37 dtucker Exp $ */
|
||||
/* $OpenBSD: misc.c,v 1.113 2017/08/18 05:48:04 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
|
||||
@ -29,11 +29,17 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <limits.h>
|
||||
#ifdef HAVE_LIBGEN_H
|
||||
# include <libgen.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -62,6 +68,10 @@
|
||||
#include "misc.h"
|
||||
#include "log.h"
|
||||
#include "ssh.h"
|
||||
#include "sshbuf.h"
|
||||
#include "ssherr.h"
|
||||
#include "uidswap.h"
|
||||
#include "platform.h"
|
||||
|
||||
/* remove newline at end of string */
|
||||
char *
|
||||
@ -540,7 +550,7 @@ addargs(arglist *args, char *fmt, ...)
|
||||
} else if (args->num+2 >= nalloc)
|
||||
nalloc *= 2;
|
||||
|
||||
args->list = xreallocarray(args->list, nalloc, sizeof(char *));
|
||||
args->list = xrecallocarray(args->list, args->nalloc, nalloc, sizeof(char *));
|
||||
args->nalloc = nalloc;
|
||||
args->list[args->num++] = cp;
|
||||
args->list[args->num] = NULL;
|
||||
@ -1086,6 +1096,7 @@ static const struct {
|
||||
const char *name;
|
||||
int value;
|
||||
} ipqos[] = {
|
||||
{ "none", INT_MAX }, /* can't use 0 here; that's CS0 */
|
||||
{ "af11", IPTOS_DSCP_AF11 },
|
||||
{ "af12", IPTOS_DSCP_AF12 },
|
||||
{ "af13", IPTOS_DSCP_AF13 },
|
||||
@ -1291,3 +1302,461 @@ daemonized(void)
|
||||
debug3("already daemonized");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Splits 's' into an argument vector. Handles quoted string and basic
|
||||
* escape characters (\\, \", \'). Caller must free the argument vector
|
||||
* and its members.
|
||||
*/
|
||||
int
|
||||
argv_split(const char *s, int *argcp, char ***argvp)
|
||||
{
|
||||
int r = SSH_ERR_INTERNAL_ERROR;
|
||||
int argc = 0, quote, i, j;
|
||||
char *arg, **argv = xcalloc(1, sizeof(*argv));
|
||||
|
||||
*argvp = NULL;
|
||||
*argcp = 0;
|
||||
|
||||
for (i = 0; s[i] != '\0'; i++) {
|
||||
/* Skip leading whitespace */
|
||||
if (s[i] == ' ' || s[i] == '\t')
|
||||
continue;
|
||||
|
||||
/* Start of a token */
|
||||
quote = 0;
|
||||
if (s[i] == '\\' &&
|
||||
(s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\'))
|
||||
i++;
|
||||
else if (s[i] == '\'' || s[i] == '"')
|
||||
quote = s[i++];
|
||||
|
||||
argv = xreallocarray(argv, (argc + 2), sizeof(*argv));
|
||||
arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1);
|
||||
argv[argc] = NULL;
|
||||
|
||||
/* Copy the token in, removing escapes */
|
||||
for (j = 0; s[i] != '\0'; i++) {
|
||||
if (s[i] == '\\') {
|
||||
if (s[i + 1] == '\'' ||
|
||||
s[i + 1] == '\"' ||
|
||||
s[i + 1] == '\\') {
|
||||
i++; /* Skip '\' */
|
||||
arg[j++] = s[i];
|
||||
} else {
|
||||
/* Unrecognised escape */
|
||||
arg[j++] = s[i];
|
||||
}
|
||||
} else if (quote == 0 && (s[i] == ' ' || s[i] == '\t'))
|
||||
break; /* done */
|
||||
else if (quote != 0 && s[i] == quote)
|
||||
break; /* done */
|
||||
else
|
||||
arg[j++] = s[i];
|
||||
}
|
||||
if (s[i] == '\0') {
|
||||
if (quote != 0) {
|
||||
/* Ran out of string looking for close quote */
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Success */
|
||||
*argcp = argc;
|
||||
*argvp = argv;
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
r = 0;
|
||||
out:
|
||||
if (argc != 0 && argv != NULL) {
|
||||
for (i = 0; i < argc; i++)
|
||||
free(argv[i]);
|
||||
free(argv);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reassemble an argument vector into a string, quoting and escaping as
|
||||
* necessary. Caller must free returned string.
|
||||
*/
|
||||
char *
|
||||
argv_assemble(int argc, char **argv)
|
||||
{
|
||||
int i, j, ws, r;
|
||||
char c, *ret;
|
||||
struct sshbuf *buf, *arg;
|
||||
|
||||
if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
ws = 0;
|
||||
sshbuf_reset(arg);
|
||||
for (j = 0; argv[i][j] != '\0'; j++) {
|
||||
r = 0;
|
||||
c = argv[i][j];
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
ws = 1;
|
||||
r = sshbuf_put_u8(arg, c);
|
||||
break;
|
||||
case '\\':
|
||||
case '\'':
|
||||
case '"':
|
||||
if ((r = sshbuf_put_u8(arg, '\\')) != 0)
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
r = sshbuf_put_u8(arg, c);
|
||||
break;
|
||||
}
|
||||
if (r != 0)
|
||||
fatal("%s: sshbuf_put_u8: %s",
|
||||
__func__, ssh_err(r));
|
||||
}
|
||||
if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) ||
|
||||
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) ||
|
||||
(r = sshbuf_putb(buf, arg)) != 0 ||
|
||||
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0))
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
}
|
||||
if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL)
|
||||
fatal("%s: malloc failed", __func__);
|
||||
memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf));
|
||||
ret[sshbuf_len(buf)] = '\0';
|
||||
sshbuf_free(buf);
|
||||
sshbuf_free(arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs command in a subprocess wuth a minimal environment.
|
||||
* Returns pid on success, 0 on failure.
|
||||
* The child stdout and stderr maybe captured, left attached or sent to
|
||||
* /dev/null depending on the contents of flags.
|
||||
* "tag" is prepended to log messages.
|
||||
* NB. "command" is only used for logging; the actual command executed is
|
||||
* av[0].
|
||||
*/
|
||||
pid_t
|
||||
subprocess(const char *tag, struct passwd *pw, const char *command,
|
||||
int ac, char **av, FILE **child, u_int flags)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
struct stat st;
|
||||
int fd, devnull, p[2], i;
|
||||
pid_t pid;
|
||||
char *cp, errmsg[512];
|
||||
u_int envsize;
|
||||
char **child_env;
|
||||
|
||||
if (child != NULL)
|
||||
*child = NULL;
|
||||
|
||||
debug3("%s: %s command \"%s\" running as %s (flags 0x%x)", __func__,
|
||||
tag, command, pw->pw_name, flags);
|
||||
|
||||
/* Check consistency */
|
||||
if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 &&
|
||||
(flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) {
|
||||
error("%s: inconsistent flags", __func__);
|
||||
return 0;
|
||||
}
|
||||
if (((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) != (child == NULL)) {
|
||||
error("%s: inconsistent flags/output", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If executing an explicit binary, then verify the it exists
|
||||
* and appears safe-ish to execute
|
||||
*/
|
||||
if (*av[0] != '/') {
|
||||
error("%s path is not absolute", tag);
|
||||
return 0;
|
||||
}
|
||||
temporarily_use_uid(pw);
|
||||
if (stat(av[0], &st) < 0) {
|
||||
error("Could not stat %s \"%s\": %s", tag,
|
||||
av[0], strerror(errno));
|
||||
restore_uid();
|
||||
return 0;
|
||||
}
|
||||
if (safe_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) {
|
||||
error("Unsafe %s \"%s\": %s", tag, av[0], errmsg);
|
||||
restore_uid();
|
||||
return 0;
|
||||
}
|
||||
/* Prepare to keep the child's stdout if requested */
|
||||
if (pipe(p) != 0) {
|
||||
error("%s: pipe: %s", tag, strerror(errno));
|
||||
restore_uid();
|
||||
return 0;
|
||||
}
|
||||
restore_uid();
|
||||
|
||||
switch ((pid = fork())) {
|
||||
case -1: /* error */
|
||||
error("%s: fork: %s", tag, strerror(errno));
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
return 0;
|
||||
case 0: /* child */
|
||||
/* Prepare a minimal environment for the child. */
|
||||
envsize = 5;
|
||||
child_env = xcalloc(sizeof(*child_env), envsize);
|
||||
child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH);
|
||||
child_set_env(&child_env, &envsize, "USER", pw->pw_name);
|
||||
child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name);
|
||||
child_set_env(&child_env, &envsize, "HOME", pw->pw_dir);
|
||||
if ((cp = getenv("LANG")) != NULL)
|
||||
child_set_env(&child_env, &envsize, "LANG", cp);
|
||||
|
||||
for (i = 0; i < NSIG; i++)
|
||||
signal(i, SIG_DFL);
|
||||
|
||||
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
|
||||
error("%s: open %s: %s", tag, _PATH_DEVNULL,
|
||||
strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
if (dup2(devnull, STDIN_FILENO) == -1) {
|
||||
error("%s: dup2: %s", tag, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
/* Set up stdout as requested; leave stderr in place for now. */
|
||||
fd = -1;
|
||||
if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0)
|
||||
fd = p[1];
|
||||
else if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0)
|
||||
fd = devnull;
|
||||
if (fd != -1 && dup2(fd, STDOUT_FILENO) == -1) {
|
||||
error("%s: dup2: %s", tag, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
|
||||
/* Don't use permanently_set_uid() here to avoid fatal() */
|
||||
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
|
||||
error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
|
||||
strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
|
||||
error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid,
|
||||
strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
/* stdin is pointed to /dev/null at this point */
|
||||
if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 &&
|
||||
dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
|
||||
error("%s: dup2: %s", tag, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
execve(av[0], av, child_env);
|
||||
error("%s exec \"%s\": %s", tag, command, strerror(errno));
|
||||
_exit(127);
|
||||
default: /* parent */
|
||||
break;
|
||||
}
|
||||
|
||||
close(p[1]);
|
||||
if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0)
|
||||
close(p[0]);
|
||||
else if ((f = fdopen(p[0], "r")) == NULL) {
|
||||
error("%s: fdopen: %s", tag, strerror(errno));
|
||||
close(p[0]);
|
||||
/* Don't leave zombie child */
|
||||
kill(pid, SIGTERM);
|
||||
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
/* Success */
|
||||
debug3("%s: %s pid %ld", __func__, tag, (long)pid);
|
||||
if (child != NULL)
|
||||
*child = f;
|
||||
return pid;
|
||||
}
|
||||
|
||||
/* Returns 0 if pid exited cleanly, non-zero otherwise */
|
||||
int
|
||||
exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet)
|
||||
{
|
||||
int status;
|
||||
|
||||
while (waitpid(pid, &status, 0) == -1) {
|
||||
if (errno != EINTR) {
|
||||
error("%s: waitpid: %s", tag, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (WIFSIGNALED(status)) {
|
||||
error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status));
|
||||
return -1;
|
||||
} else if (WEXITSTATUS(status) != 0) {
|
||||
do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO,
|
||||
"%s %s failed, status %d", tag, cmd, WEXITSTATUS(status));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a given path for security. This is defined as all components
|
||||
* of the path to the file must be owned by either the owner of
|
||||
* of the file or root and no directories must be group or world writable.
|
||||
*
|
||||
* XXX Should any specific check be done for sym links ?
|
||||
*
|
||||
* Takes a file name, its stat information (preferably from fstat() to
|
||||
* avoid races), the uid of the expected owner, their home directory and an
|
||||
* error buffer plus max size as arguments.
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
int
|
||||
safe_path(const char *name, struct stat *stp, const char *pw_dir,
|
||||
uid_t uid, char *err, size_t errlen)
|
||||
{
|
||||
char buf[PATH_MAX], homedir[PATH_MAX];
|
||||
char *cp;
|
||||
int comparehome = 0;
|
||||
struct stat st;
|
||||
|
||||
if (realpath(name, buf) == NULL) {
|
||||
snprintf(err, errlen, "realpath %s failed: %s", name,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
|
||||
comparehome = 1;
|
||||
|
||||
if (!S_ISREG(stp->st_mode)) {
|
||||
snprintf(err, errlen, "%s is not a regular file", buf);
|
||||
return -1;
|
||||
}
|
||||
if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
|
||||
(stp->st_mode & 022) != 0) {
|
||||
snprintf(err, errlen, "bad ownership or modes for file %s",
|
||||
buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* for each component of the canonical path, walking upwards */
|
||||
for (;;) {
|
||||
if ((cp = dirname(buf)) == NULL) {
|
||||
snprintf(err, errlen, "dirname() failed");
|
||||
return -1;
|
||||
}
|
||||
strlcpy(buf, cp, sizeof(buf));
|
||||
|
||||
if (stat(buf, &st) < 0 ||
|
||||
(!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
|
||||
(st.st_mode & 022) != 0) {
|
||||
snprintf(err, errlen,
|
||||
"bad ownership or modes for directory %s", buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If are past the homedir then we can stop */
|
||||
if (comparehome && strcmp(homedir, buf) == 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* dirname should always complete with a "/" path,
|
||||
* but we can be paranoid and check for "." too
|
||||
*/
|
||||
if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Version of safe_path() that accepts an open file descriptor to
|
||||
* avoid races.
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
int
|
||||
safe_path_fd(int fd, const char *file, struct passwd *pw,
|
||||
char *err, size_t errlen)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
/* check the open file to avoid races */
|
||||
if (fstat(fd, &st) < 0) {
|
||||
snprintf(err, errlen, "cannot stat file %s: %s",
|
||||
file, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the value of the given variable in the environment. If the variable
|
||||
* already exists, its value is overridden.
|
||||
*/
|
||||
void
|
||||
child_set_env(char ***envp, u_int *envsizep, const char *name,
|
||||
const char *value)
|
||||
{
|
||||
char **env;
|
||||
u_int envsize;
|
||||
u_int i, namelen;
|
||||
|
||||
if (strchr(name, '=') != NULL) {
|
||||
error("Invalid environment variable \"%.100s\"", name);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're passed an uninitialized list, allocate a single null
|
||||
* entry before continuing.
|
||||
*/
|
||||
if (*envp == NULL && *envsizep == 0) {
|
||||
*envp = xmalloc(sizeof(char *));
|
||||
*envp[0] = NULL;
|
||||
*envsizep = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the slot where the value should be stored. If the variable
|
||||
* already exists, we reuse the slot; otherwise we append a new slot
|
||||
* at the end of the array, expanding if necessary.
|
||||
*/
|
||||
env = *envp;
|
||||
namelen = strlen(name);
|
||||
for (i = 0; env[i]; i++)
|
||||
if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
|
||||
break;
|
||||
if (env[i]) {
|
||||
/* Reuse the slot. */
|
||||
free(env[i]);
|
||||
} else {
|
||||
/* New variable. Expand if necessary. */
|
||||
envsize = *envsizep;
|
||||
if (i >= envsize - 1) {
|
||||
if (envsize >= 1000)
|
||||
fatal("child_set_env: too many env vars");
|
||||
envsize += 50;
|
||||
env = (*envp) = xreallocarray(env, envsize, sizeof(char *));
|
||||
*envsizep = envsize;
|
||||
}
|
||||
/* Need to set the NULL pointer at end of array beyond the new slot. */
|
||||
env[i + 1] = NULL;
|
||||
}
|
||||
|
||||
/* Allocate space and format the variable in the appropriate slot. */
|
||||
env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
|
||||
snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: misc.h,v 1.61 2016/11/30 00:28:31 dtucker Exp $ */
|
||||
/* $OpenBSD: misc.h,v 1.63 2017/08/18 05:48:04 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -16,6 +16,7 @@
|
||||
#define _MISC_H
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Data structure for representing a forwarding request. */
|
||||
struct Forward {
|
||||
@ -132,6 +133,25 @@ int parse_ipqos(const char *);
|
||||
const char *iptos2str(int);
|
||||
void mktemp_proto(char *, size_t);
|
||||
|
||||
void child_set_env(char ***envp, u_int *envsizep, const char *name,
|
||||
const char *value);
|
||||
|
||||
int argv_split(const char *, int *, char ***);
|
||||
char *argv_assemble(int, char **argv);
|
||||
int exited_cleanly(pid_t, const char *, const char *, int);
|
||||
|
||||
#define SSH_SUBPROCESS_STDOUT_DISCARD (1) /* Discard stdout */
|
||||
#define SSH_SUBPROCESS_STDOUT_CAPTURE (1<<1) /* Redirect stdout */
|
||||
#define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */
|
||||
pid_t subprocess(const char *, struct passwd *,
|
||||
const char *, int, char **, FILE **, u_int flags);
|
||||
|
||||
struct stat;
|
||||
int safe_path(const char *, struct stat *, const char *, uid_t,
|
||||
char *, size_t);
|
||||
int safe_path_fd(int, const char *, struct passwd *,
|
||||
char *err, size_t errlen);
|
||||
|
||||
/* readpass.c */
|
||||
|
||||
#define RP_ECHO 0x0001
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: monitor.c,v 1.167 2017/02/03 23:05:57 djm Exp $ */
|
||||
/* $OpenBSD: monitor.c,v 1.174 2017/10/02 19:33:20 djm Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||
@ -308,6 +308,8 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
|
||||
partial = 0;
|
||||
auth_method = "unknown";
|
||||
auth_submethod = NULL;
|
||||
auth2_authctxt_reset_info(authctxt);
|
||||
|
||||
authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
|
||||
|
||||
/* Special handling for multiple required authentications */
|
||||
@ -347,6 +349,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
|
||||
auth_method, auth_submethod);
|
||||
if (!partial && !authenticated)
|
||||
authctxt->failures++;
|
||||
if (authenticated || partial) {
|
||||
auth2_update_session_info(authctxt,
|
||||
auth_method, auth_submethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -754,10 +760,12 @@ mm_answer_pwnamallow(int sock, Buffer *m)
|
||||
for (i = 0; i < options.nx; i++) \
|
||||
buffer_put_cstring(m, options.x[i]); \
|
||||
} while (0)
|
||||
#define M_CP_STRARRAYOPT_ALLOC(x, nx) M_CP_STRARRAYOPT(x, nx)
|
||||
/* See comment in servconf.h */
|
||||
COPY_MATCH_STRING_OPTS();
|
||||
#undef M_CP_STROPT
|
||||
#undef M_CP_STRARRAYOPT
|
||||
#undef M_CP_STRARRAYOPT_ALLOC
|
||||
|
||||
/* Create valid auth method lists */
|
||||
if (auth2_setup_methods_lists(authctxt) != 0) {
|
||||
@ -1119,7 +1127,7 @@ mm_answer_pam_free_ctx(int sock, Buffer *m)
|
||||
int
|
||||
mm_answer_keyallowed(int sock, Buffer *m)
|
||||
{
|
||||
Key *key;
|
||||
struct sshkey *key;
|
||||
char *cuser, *chost;
|
||||
u_char *blob;
|
||||
u_int bloblen, pubkey_auth_attempt;
|
||||
@ -1147,12 +1155,11 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
||||
switch (type) {
|
||||
case MM_USERKEY:
|
||||
allowed = options.pubkey_authentication &&
|
||||
!auth2_userkey_already_used(authctxt, key) &&
|
||||
!auth2_key_already_used(authctxt, key) &&
|
||||
match_pattern_list(sshkey_ssh_name(key),
|
||||
options.pubkey_key_types, 0) == 1 &&
|
||||
user_key_allowed(authctxt->pw, key,
|
||||
pubkey_auth_attempt);
|
||||
pubkey_auth_info(authctxt, key, NULL);
|
||||
auth_method = "publickey";
|
||||
if (options.pubkey_authentication &&
|
||||
(!pubkey_auth_attempt || allowed != 1))
|
||||
@ -1160,11 +1167,12 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
||||
break;
|
||||
case MM_HOSTKEY:
|
||||
allowed = options.hostbased_authentication &&
|
||||
!auth2_key_already_used(authctxt, key) &&
|
||||
match_pattern_list(sshkey_ssh_name(key),
|
||||
options.hostbased_key_types, 0) == 1 &&
|
||||
hostbased_key_allowed(authctxt->pw,
|
||||
cuser, chost, key);
|
||||
pubkey_auth_info(authctxt, key,
|
||||
auth2_record_info(authctxt,
|
||||
"client user \"%.100s\", client host \"%.100s\"",
|
||||
cuser, chost);
|
||||
auth_method = "hostbased";
|
||||
@ -1175,11 +1183,10 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
||||
}
|
||||
}
|
||||
|
||||
debug3("%s: key %p is %s",
|
||||
__func__, key, allowed ? "allowed" : "not allowed");
|
||||
debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed");
|
||||
|
||||
if (key != NULL)
|
||||
key_free(key);
|
||||
auth2_record_key(authctxt, 0, key);
|
||||
sshkey_free(key);
|
||||
|
||||
/* clear temporarily storage (used by verify) */
|
||||
monitor_reset_key_state();
|
||||
@ -1330,33 +1337,35 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
|
||||
}
|
||||
|
||||
int
|
||||
mm_answer_keyverify(int sock, Buffer *m)
|
||||
mm_answer_keyverify(int sock, struct sshbuf *m)
|
||||
{
|
||||
Key *key;
|
||||
struct sshkey *key;
|
||||
u_char *signature, *data, *blob;
|
||||
u_int signaturelen, datalen, bloblen;
|
||||
int verified = 0;
|
||||
int valid_data = 0;
|
||||
size_t signaturelen, datalen, bloblen;
|
||||
int r, ret, valid_data = 0, encoded_ret;
|
||||
|
||||
blob = buffer_get_string(m, &bloblen);
|
||||
signature = buffer_get_string(m, &signaturelen);
|
||||
data = buffer_get_string(m, &datalen);
|
||||
if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 ||
|
||||
(r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 ||
|
||||
(r = sshbuf_get_string(m, &data, &datalen)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
|
||||
if (hostbased_cuser == NULL || hostbased_chost == NULL ||
|
||||
!monitor_allowed_key(blob, bloblen))
|
||||
fatal("%s: bad key, not previously allowed", __func__);
|
||||
|
||||
key = key_from_blob(blob, bloblen);
|
||||
if (key == NULL)
|
||||
fatal("%s: bad public key blob", __func__);
|
||||
/* XXX use sshkey_froms here; need to change key_blob, etc. */
|
||||
if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0)
|
||||
fatal("%s: bad public key blob: %s", __func__, ssh_err(r));
|
||||
|
||||
switch (key_blobtype) {
|
||||
case MM_USERKEY:
|
||||
valid_data = monitor_valid_userblob(data, datalen);
|
||||
auth_method = "publickey";
|
||||
break;
|
||||
case MM_HOSTKEY:
|
||||
valid_data = monitor_valid_hostbasedblob(data, datalen,
|
||||
hostbased_cuser, hostbased_chost);
|
||||
auth_method = "hostbased";
|
||||
break;
|
||||
default:
|
||||
valid_data = 0;
|
||||
@ -1365,29 +1374,28 @@ mm_answer_keyverify(int sock, Buffer *m)
|
||||
if (!valid_data)
|
||||
fatal("%s: bad signature data blob", __func__);
|
||||
|
||||
verified = key_verify(key, signature, signaturelen, data, datalen);
|
||||
debug3("%s: key %p signature %s",
|
||||
__func__, key, (verified == 1) ? "verified" : "unverified");
|
||||
|
||||
/* If auth was successful then record key to ensure it isn't reused */
|
||||
if (verified == 1 && key_blobtype == MM_USERKEY)
|
||||
auth2_record_userkey(authctxt, key);
|
||||
else
|
||||
key_free(key);
|
||||
ret = sshkey_verify(key, signature, signaturelen, data, datalen,
|
||||
active_state->compat);
|
||||
debug3("%s: %s %p signature %s", __func__, auth_method, key,
|
||||
(ret == 0) ? "verified" : "unverified");
|
||||
auth2_record_key(authctxt, ret == 0, key);
|
||||
|
||||
free(blob);
|
||||
free(signature);
|
||||
free(data);
|
||||
|
||||
auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased";
|
||||
|
||||
monitor_reset_key_state();
|
||||
|
||||
buffer_clear(m);
|
||||
buffer_put_int(m, verified);
|
||||
sshkey_free(key);
|
||||
sshbuf_reset(m);
|
||||
|
||||
/* encode ret != 0 as positive integer, since we're sending u32 */
|
||||
encoded_ret = (ret != 0);
|
||||
if ((r = sshbuf_put_u32(m, encoded_ret)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
|
||||
|
||||
return (verified == 1);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1513,13 +1521,14 @@ mm_answer_pty_cleanup(int sock, Buffer *m)
|
||||
int
|
||||
mm_answer_term(int sock, Buffer *req)
|
||||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
extern struct monitor *pmonitor;
|
||||
int res, status;
|
||||
|
||||
debug3("%s: tearing down sessions", __func__);
|
||||
|
||||
/* The child is terminating */
|
||||
session_destroy_all(&mm_session_close);
|
||||
session_destroy_all(ssh, &mm_session_close);
|
||||
|
||||
#ifdef USE_PAM
|
||||
if (options.use_pam)
|
||||
@ -1578,6 +1587,17 @@ mm_answer_audit_command(int socket, Buffer *m)
|
||||
}
|
||||
#endif /* SSH_AUDIT_EVENTS */
|
||||
|
||||
void
|
||||
monitor_clear_keystate(struct monitor *pmonitor)
|
||||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
|
||||
ssh_clear_newkeys(ssh, MODE_IN);
|
||||
ssh_clear_newkeys(ssh, MODE_OUT);
|
||||
sshbuf_free(child_state);
|
||||
child_state = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
monitor_apply_keystate(struct monitor *pmonitor)
|
||||
{
|
||||
@ -1639,9 +1659,18 @@ static void
|
||||
monitor_openfds(struct monitor *mon, int do_logfds)
|
||||
{
|
||||
int pair[2];
|
||||
#ifdef SO_ZEROIZE
|
||||
int on = 1;
|
||||
#endif
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
|
||||
fatal("%s: socketpair: %s", __func__, strerror(errno));
|
||||
#ifdef SO_ZEROIZE
|
||||
if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0)
|
||||
error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno));
|
||||
if (setsockopt(pair[1], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0)
|
||||
error("setsockopt SO_ZEROIZE(1): %.100s", strerror(errno));
|
||||
#endif
|
||||
FD_CLOSEONEXEC(pair[0]);
|
||||
FD_CLOSEONEXEC(pair[1]);
|
||||
mon->m_recvfd = pair[0];
|
||||
@ -1774,6 +1803,7 @@ int
|
||||
mm_answer_gss_userok(int sock, Buffer *m)
|
||||
{
|
||||
int authenticated;
|
||||
const char *displayname;
|
||||
|
||||
if (!options.gss_authentication)
|
||||
fatal("%s: GSSAPI authentication not enabled", __func__);
|
||||
@ -1788,6 +1818,9 @@ mm_answer_gss_userok(int sock, Buffer *m)
|
||||
|
||||
auth_method = "gssapi-with-mic";
|
||||
|
||||
if ((displayname = ssh_gssapi_displayname()) != NULL)
|
||||
auth2_record_info(authctxt, "%s", displayname);
|
||||
|
||||
/* Monitor loop will terminate if authenticated */
|
||||
return (authenticated);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: monitor_wrap.c,v 1.89 2016/08/13 17:47:41 markus Exp $ */
|
||||
/* $OpenBSD: monitor_wrap.c,v 1.94 2017/10/02 19:33:20 djm Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* Copyright 2002 Markus Friedl <markus@openbsd.org>
|
||||
@ -216,7 +216,7 @@ mm_choose_dh(int min, int nbits, int max)
|
||||
#endif
|
||||
|
||||
int
|
||||
mm_key_sign(Key *key, u_char **sigp, u_int *lenp,
|
||||
mm_key_sign(struct sshkey *key, u_char **sigp, u_int *lenp,
|
||||
const u_char *data, u_int datalen, const char *hostkey_alg)
|
||||
{
|
||||
struct kex *kex = *pmonitor->m_pkex;
|
||||
@ -242,6 +242,7 @@ mm_key_sign(Key *key, u_char **sigp, u_int *lenp,
|
||||
struct passwd *
|
||||
mm_getpwnamallow(const char *username)
|
||||
{
|
||||
struct ssh *ssh = active_state; /* XXX */
|
||||
Buffer m;
|
||||
struct passwd *pw;
|
||||
u_int len, i;
|
||||
@ -289,12 +290,20 @@ mm_getpwnamallow(const char *username)
|
||||
for (i = 0; i < newopts->nx; i++) \
|
||||
newopts->x[i] = buffer_get_string(&m, NULL); \
|
||||
} while (0)
|
||||
#define M_CP_STRARRAYOPT_ALLOC(x, nx) do { \
|
||||
newopts->x = newopts->nx == 0 ? \
|
||||
NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \
|
||||
M_CP_STRARRAYOPT(x, nx); \
|
||||
} while (0)
|
||||
/* See comment in servconf.h */
|
||||
COPY_MATCH_STRING_OPTS();
|
||||
#undef M_CP_STROPT
|
||||
#undef M_CP_STRARRAYOPT
|
||||
#undef M_CP_STRARRAYOPT_ALLOC
|
||||
|
||||
copy_set_server_options(&options, newopts, 1);
|
||||
log_change_level(options.log_level);
|
||||
process_permitopen(ssh, &options);
|
||||
free(newopts);
|
||||
|
||||
buffer_free(&m);
|
||||
@ -374,7 +383,8 @@ mm_auth_password(Authctxt *authctxt, char *password)
|
||||
}
|
||||
|
||||
int
|
||||
mm_user_key_allowed(struct passwd *pw, Key *key, int pubkey_auth_attempt)
|
||||
mm_user_key_allowed(struct passwd *pw, struct sshkey *key,
|
||||
int pubkey_auth_attempt)
|
||||
{
|
||||
return (mm_key_allowed(MM_USERKEY, NULL, NULL, key,
|
||||
pubkey_auth_attempt));
|
||||
@ -382,14 +392,14 @@ mm_user_key_allowed(struct passwd *pw, Key *key, int pubkey_auth_attempt)
|
||||
|
||||
int
|
||||
mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host,
|
||||
Key *key)
|
||||
struct sshkey *key)
|
||||
{
|
||||
return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0));
|
||||
}
|
||||
|
||||
int
|
||||
mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
|
||||
Key *key, int pubkey_auth_attempt)
|
||||
struct sshkey *key, int pubkey_auth_attempt)
|
||||
{
|
||||
Buffer m;
|
||||
u_char *blob;
|
||||
@ -434,12 +444,13 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
|
||||
*/
|
||||
|
||||
int
|
||||
mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
|
||||
mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
{
|
||||
Buffer m;
|
||||
u_char *blob;
|
||||
u_int len;
|
||||
int verified = 0;
|
||||
u_int encoded_ret = 0;
|
||||
|
||||
debug3("%s entering", __func__);
|
||||
|
||||
@ -458,11 +469,13 @@ mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
|
||||
debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
|
||||
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m);
|
||||
|
||||
verified = buffer_get_int(&m);
|
||||
encoded_ret = buffer_get_int(&m);
|
||||
|
||||
buffer_free(&m);
|
||||
|
||||
return (verified);
|
||||
if (encoded_ret != 0)
|
||||
return SSH_ERR_SIGNATURE_INVALID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: monitor_wrap.h,v 1.32 2016/09/28 16:33:07 djm Exp $ */
|
||||
/* $OpenBSD: monitor_wrap.h,v 1.35 2017/05/31 08:09:45 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
@ -34,22 +34,24 @@ extern int use_privsep;
|
||||
enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY };
|
||||
|
||||
struct monitor;
|
||||
struct mm_master;
|
||||
struct Authctxt;
|
||||
|
||||
void mm_log_handler(LogLevel, const char *, void *);
|
||||
int mm_is_monitor(void);
|
||||
DH *mm_choose_dh(int, int, int);
|
||||
int mm_key_sign(Key *, u_char **, u_int *, const u_char *, u_int, const char *);
|
||||
int mm_key_sign(struct sshkey *, u_char **, u_int *, const u_char *, u_int,
|
||||
const char *);
|
||||
void mm_inform_authserv(char *, char *);
|
||||
struct passwd *mm_getpwnamallow(const char *);
|
||||
char *mm_auth2_read_banner(void);
|
||||
int mm_auth_password(struct Authctxt *, char *);
|
||||
int mm_key_allowed(enum mm_keytype, const char *, const char *, Key *, int);
|
||||
int mm_user_key_allowed(struct passwd *, Key *, int);
|
||||
int mm_key_allowed(enum mm_keytype, const char *, const char *, struct sshkey *,
|
||||
int);
|
||||
int mm_user_key_allowed(struct passwd *, struct sshkey *, int);
|
||||
int mm_hostbased_key_allowed(struct passwd *, const char *,
|
||||
const char *, Key *);
|
||||
int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
|
||||
const char *, struct sshkey *);
|
||||
int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t,
|
||||
const u_char *, size_t, u_int);
|
||||
|
||||
#ifdef GSSAPI
|
||||
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
|
||||
@ -83,6 +85,7 @@ void mm_session_pty_cleanup2(struct Session *);
|
||||
struct newkeys *mm_newkeys_from_blob(u_char *, int);
|
||||
int mm_newkeys_to_blob(int, u_char **, u_int *);
|
||||
|
||||
void monitor_clear_keystate(struct monitor *);
|
||||
void monitor_apply_keystate(struct monitor *);
|
||||
void mm_get_keystate(struct monitor *);
|
||||
void mm_send_keystate(struct monitor*);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: mux.c,v 1.64 2017/01/21 11:32:04 guenther Exp $ */
|
||||
/* $OpenBSD: mux.c,v 1.69 2017/09/20 05:19:00 dtucker Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
|
||||
*
|
||||
@ -162,22 +162,32 @@ struct mux_master_state {
|
||||
#define MUX_FWD_REMOTE 2
|
||||
#define MUX_FWD_DYNAMIC 3
|
||||
|
||||
static void mux_session_confirm(int, int, void *);
|
||||
static void mux_stdio_confirm(int, int, void *);
|
||||
static void mux_session_confirm(struct ssh *, int, int, void *);
|
||||
static void mux_stdio_confirm(struct ssh *, int, int, void *);
|
||||
|
||||
static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *);
|
||||
static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *);
|
||||
static int process_mux_alive_check(u_int, Channel *, Buffer *, Buffer *);
|
||||
static int process_mux_terminate(u_int, Channel *, Buffer *, Buffer *);
|
||||
static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *);
|
||||
static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *);
|
||||
static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *);
|
||||
static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *);
|
||||
static int process_mux_proxy(u_int, Channel *, Buffer *, Buffer *);
|
||||
static int process_mux_master_hello(struct ssh *, u_int,
|
||||
Channel *, struct sshbuf *, struct sshbuf *);
|
||||
static int process_mux_new_session(struct ssh *, u_int,
|
||||
Channel *, struct sshbuf *, struct sshbuf *);
|
||||
static int process_mux_alive_check(struct ssh *, u_int,
|
||||
Channel *, struct sshbuf *, struct sshbuf *);
|
||||
static int process_mux_terminate(struct ssh *, u_int,
|
||||
Channel *, struct sshbuf *, struct sshbuf *);
|
||||
static int process_mux_open_fwd(struct ssh *, u_int,
|
||||
Channel *, struct sshbuf *, struct sshbuf *);
|
||||
static int process_mux_close_fwd(struct ssh *, u_int,
|
||||
Channel *, struct sshbuf *, struct sshbuf *);
|
||||
static int process_mux_stdio_fwd(struct ssh *, u_int,
|
||||
Channel *, struct sshbuf *, struct sshbuf *);
|
||||
static int process_mux_stop_listening(struct ssh *, u_int,
|
||||
Channel *, struct sshbuf *, struct sshbuf *);
|
||||
static int process_mux_proxy(struct ssh *, u_int,
|
||||
Channel *, struct sshbuf *, struct sshbuf *);
|
||||
|
||||
static const struct {
|
||||
u_int type;
|
||||
int (*handler)(u_int, Channel *, Buffer *, Buffer *);
|
||||
int (*handler)(struct ssh *, u_int, Channel *,
|
||||
struct sshbuf *, struct sshbuf *);
|
||||
} mux_master_handlers[] = {
|
||||
{ MUX_MSG_HELLO, process_mux_master_hello },
|
||||
{ MUX_C_NEW_SESSION, process_mux_new_session },
|
||||
@ -194,52 +204,54 @@ static const struct {
|
||||
/* Cleanup callback fired on closure of mux slave _session_ channel */
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
mux_master_session_cleanup_cb(int cid, void *unused)
|
||||
mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused)
|
||||
{
|
||||
Channel *cc, *c = channel_by_id(cid);
|
||||
Channel *cc, *c = channel_by_id(ssh, cid);
|
||||
|
||||
debug3("%s: entering for channel %d", __func__, cid);
|
||||
if (c == NULL)
|
||||
fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
|
||||
if (c->ctl_chan != -1) {
|
||||
if ((cc = channel_by_id(c->ctl_chan)) == NULL)
|
||||
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
|
||||
fatal("%s: channel %d missing control channel %d",
|
||||
__func__, c->self, c->ctl_chan);
|
||||
c->ctl_chan = -1;
|
||||
cc->remote_id = -1;
|
||||
chan_rcvd_oclose(cc);
|
||||
cc->remote_id = 0;
|
||||
cc->have_remote_id = 0;
|
||||
chan_rcvd_oclose(ssh, cc);
|
||||
}
|
||||
channel_cancel_cleanup(c->self);
|
||||
channel_cancel_cleanup(ssh, c->self);
|
||||
}
|
||||
|
||||
/* Cleanup callback fired on closure of mux slave _control_ channel */
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
mux_master_control_cleanup_cb(int cid, void *unused)
|
||||
mux_master_control_cleanup_cb(struct ssh *ssh, int cid, void *unused)
|
||||
{
|
||||
Channel *sc, *c = channel_by_id(cid);
|
||||
Channel *sc, *c = channel_by_id(ssh, cid);
|
||||
|
||||
debug3("%s: entering for channel %d", __func__, cid);
|
||||
if (c == NULL)
|
||||
fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
|
||||
if (c->remote_id != -1) {
|
||||
if ((sc = channel_by_id(c->remote_id)) == NULL)
|
||||
fatal("%s: channel %d missing session channel %d",
|
||||
if (c->have_remote_id) {
|
||||
if ((sc = channel_by_id(ssh, c->remote_id)) == NULL)
|
||||
fatal("%s: channel %d missing session channel %u",
|
||||
__func__, c->self, c->remote_id);
|
||||
c->remote_id = -1;
|
||||
c->remote_id = 0;
|
||||
c->have_remote_id = 0;
|
||||
sc->ctl_chan = -1;
|
||||
if (sc->type != SSH_CHANNEL_OPEN &&
|
||||
sc->type != SSH_CHANNEL_OPENING) {
|
||||
debug2("%s: channel %d: not open", __func__, sc->self);
|
||||
chan_mark_dead(sc);
|
||||
chan_mark_dead(ssh, sc);
|
||||
} else {
|
||||
if (sc->istate == CHAN_INPUT_OPEN)
|
||||
chan_read_failed(sc);
|
||||
chan_read_failed(ssh, sc);
|
||||
if (sc->ostate == CHAN_OUTPUT_OPEN)
|
||||
chan_write_failed(sc);
|
||||
chan_write_failed(ssh, sc);
|
||||
}
|
||||
}
|
||||
channel_cancel_cleanup(c->self);
|
||||
channel_cancel_cleanup(ssh, c->self);
|
||||
}
|
||||
|
||||
/* Check mux client environment variables before passing them to mux master. */
|
||||
@ -267,7 +279,8 @@ env_permitted(char *env)
|
||||
/* Mux master protocol message handlers */
|
||||
|
||||
static int
|
||||
process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
process_mux_master_hello(struct ssh *ssh, u_int rid,
|
||||
Channel *c, Buffer *m, Buffer *r)
|
||||
{
|
||||
u_int ver;
|
||||
struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
|
||||
@ -309,7 +322,8 @@ process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
}
|
||||
|
||||
static int
|
||||
process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
process_mux_new_session(struct ssh *ssh, u_int rid,
|
||||
Channel *c, Buffer *m, Buffer *r)
|
||||
{
|
||||
Channel *nc;
|
||||
struct mux_session_confirm_ctx *cctx;
|
||||
@ -402,7 +416,7 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
new_fd[0], new_fd[1], new_fd[2]);
|
||||
|
||||
/* XXX support multiple child sessions in future */
|
||||
if (c->remote_id != -1) {
|
||||
if (c->have_remote_id) {
|
||||
debug2("%s: session already open", __func__);
|
||||
/* prepare reply */
|
||||
buffer_put_int(r, MUX_S_FAILURE);
|
||||
@ -454,15 +468,16 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
packetmax >>= 1;
|
||||
}
|
||||
|
||||
nc = channel_new("session", SSH_CHANNEL_OPENING,
|
||||
nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING,
|
||||
new_fd[0], new_fd[1], new_fd[2], window, packetmax,
|
||||
CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
|
||||
|
||||
nc->ctl_chan = c->self; /* link session -> control channel */
|
||||
c->remote_id = nc->self; /* link control -> session channel */
|
||||
c->have_remote_id = 1;
|
||||
|
||||
if (cctx->want_tty && escape_char != 0xffffffff) {
|
||||
channel_register_filter(nc->self,
|
||||
channel_register_filter(ssh, nc->self,
|
||||
client_simple_escape_filter, NULL,
|
||||
client_filter_cleanup,
|
||||
client_new_escape_filter_ctx((int)escape_char));
|
||||
@ -471,17 +486,19 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
debug2("%s: channel_new: %d linked to control channel %d",
|
||||
__func__, nc->self, nc->ctl_chan);
|
||||
|
||||
channel_send_open(nc->self);
|
||||
channel_register_open_confirm(nc->self, mux_session_confirm, cctx);
|
||||
channel_send_open(ssh, nc->self);
|
||||
channel_register_open_confirm(ssh, nc->self, mux_session_confirm, cctx);
|
||||
c->mux_pause = 1; /* stop handling messages until open_confirm done */
|
||||
channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
|
||||
channel_register_cleanup(ssh, nc->self,
|
||||
mux_master_session_cleanup_cb, 1);
|
||||
|
||||
/* reply is deferred, sent by mux_session_confirm */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
process_mux_alive_check(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
process_mux_alive_check(struct ssh *ssh, u_int rid,
|
||||
Channel *c, Buffer *m, Buffer *r)
|
||||
{
|
||||
debug2("%s: channel %d: alive check", __func__, c->self);
|
||||
|
||||
@ -494,7 +511,8 @@ process_mux_alive_check(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
}
|
||||
|
||||
static int
|
||||
process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
process_mux_terminate(struct ssh *ssh, u_int rid,
|
||||
Channel *c, Buffer *m, Buffer *r)
|
||||
{
|
||||
debug2("%s: channel %d: terminate request", __func__, c->self);
|
||||
|
||||
@ -583,7 +601,7 @@ compare_forward(struct Forward *a, struct Forward *b)
|
||||
}
|
||||
|
||||
static void
|
||||
mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||
mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
|
||||
{
|
||||
struct mux_channel_confirm_ctx *fctx = ctxt;
|
||||
char *failmsg = NULL;
|
||||
@ -591,7 +609,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||
Channel *c;
|
||||
Buffer out;
|
||||
|
||||
if ((c = channel_by_id(fctx->cid)) == NULL) {
|
||||
if ((c = channel_by_id(ssh, fctx->cid)) == NULL) {
|
||||
/* no channel for reply */
|
||||
error("%s: unknown channel", __func__);
|
||||
return;
|
||||
@ -617,7 +635,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||
buffer_put_int(&out, MUX_S_REMOTE_PORT);
|
||||
buffer_put_int(&out, fctx->rid);
|
||||
buffer_put_int(&out, rfwd->allocated_port);
|
||||
channel_update_permitted_opens(rfwd->handle,
|
||||
channel_update_permitted_opens(ssh, rfwd->handle,
|
||||
rfwd->allocated_port);
|
||||
} else {
|
||||
buffer_put_int(&out, MUX_S_OK);
|
||||
@ -626,7 +644,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||
goto out;
|
||||
} else {
|
||||
if (rfwd->listen_port == 0)
|
||||
channel_update_permitted_opens(rfwd->handle, -1);
|
||||
channel_update_permitted_opens(ssh, rfwd->handle, -1);
|
||||
if (rfwd->listen_path != NULL)
|
||||
xasprintf(&failmsg, "remote port forwarding failed for "
|
||||
"listen path %s", rfwd->listen_path);
|
||||
@ -652,7 +670,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||
buffer_put_cstring(&out, failmsg);
|
||||
free(failmsg);
|
||||
out:
|
||||
buffer_put_string(&c->output, buffer_ptr(&out), buffer_len(&out));
|
||||
buffer_put_string(c->output, buffer_ptr(&out), buffer_len(&out));
|
||||
buffer_free(&out);
|
||||
if (c->mux_pause <= 0)
|
||||
fatal("%s: mux_pause %d", __func__, c->mux_pause);
|
||||
@ -660,7 +678,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
|
||||
}
|
||||
|
||||
static int
|
||||
process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
process_mux_open_fwd(struct ssh *ssh, u_int rid,
|
||||
Channel *c, Buffer *m, Buffer *r)
|
||||
{
|
||||
struct Forward fwd;
|
||||
char *fwd_desc = NULL;
|
||||
@ -728,13 +747,16 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
fwd.listen_port);
|
||||
goto invalid;
|
||||
}
|
||||
if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536)
|
||||
|| (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
|
||||
if ((fwd.connect_port != PORT_STREAMLOCAL &&
|
||||
fwd.connect_port >= 65536) ||
|
||||
(ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE &&
|
||||
fwd.connect_port == 0)) {
|
||||
logit("%s: invalid connect port %u", __func__,
|
||||
fwd.connect_port);
|
||||
goto invalid;
|
||||
}
|
||||
if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) {
|
||||
if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL &&
|
||||
fwd.connect_path == NULL) {
|
||||
logit("%s: missing connect host", __func__);
|
||||
goto invalid;
|
||||
}
|
||||
@ -785,7 +807,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
}
|
||||
|
||||
if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
|
||||
if (!channel_setup_local_fwd_listener(&fwd,
|
||||
if (!channel_setup_local_fwd_listener(ssh, &fwd,
|
||||
&options.fwd_opts)) {
|
||||
fail:
|
||||
logit("slave-requested %s failed", fwd_desc);
|
||||
@ -799,7 +821,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
} else {
|
||||
struct mux_channel_confirm_ctx *fctx;
|
||||
|
||||
fwd.handle = channel_request_remote_forwarding(&fwd);
|
||||
fwd.handle = channel_request_remote_forwarding(ssh, &fwd);
|
||||
if (fwd.handle < 0)
|
||||
goto fail;
|
||||
add_remote_forward(&options, &fwd);
|
||||
@ -828,7 +850,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
}
|
||||
|
||||
static int
|
||||
process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
process_mux_close_fwd(struct ssh *ssh, u_int rid,
|
||||
Channel *c, Buffer *m, Buffer *r)
|
||||
{
|
||||
struct Forward fwd, *found_fwd;
|
||||
char *fwd_desc = NULL;
|
||||
@ -909,11 +932,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
* However, for dynamic allocated listen ports we need
|
||||
* to use the actual listen port.
|
||||
*/
|
||||
if (channel_request_rforward_cancel(found_fwd) == -1)
|
||||
if (channel_request_rforward_cancel(ssh, found_fwd) == -1)
|
||||
error_reason = "port not in permitted opens";
|
||||
} else { /* local and dynamic forwards */
|
||||
/* Ditto */
|
||||
if (channel_cancel_lport_listener(&fwd, fwd.connect_port,
|
||||
if (channel_cancel_lport_listener(ssh, &fwd, fwd.connect_port,
|
||||
&options.fwd_opts) == -1)
|
||||
error_reason = "port not found";
|
||||
}
|
||||
@ -943,7 +966,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
}
|
||||
|
||||
static int
|
||||
process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
process_mux_stdio_fwd(struct ssh *ssh, u_int rid,
|
||||
Channel *c, Buffer *m, Buffer *r)
|
||||
{
|
||||
Channel *nc;
|
||||
char *reserved, *chost;
|
||||
@ -987,7 +1011,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
new_fd[0], new_fd[1]);
|
||||
|
||||
/* XXX support multiple child sessions in future */
|
||||
if (c->remote_id != -1) {
|
||||
if (c->have_remote_id) {
|
||||
debug2("%s: session already open", __func__);
|
||||
/* prepare reply */
|
||||
buffer_put_int(r, MUX_S_FAILURE);
|
||||
@ -1019,19 +1043,21 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
if (!isatty(new_fd[1]))
|
||||
set_nonblock(new_fd[1]);
|
||||
|
||||
nc = channel_connect_stdio_fwd(chost, cport, new_fd[0], new_fd[1]);
|
||||
nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]);
|
||||
|
||||
nc->ctl_chan = c->self; /* link session -> control channel */
|
||||
c->remote_id = nc->self; /* link control -> session channel */
|
||||
c->have_remote_id = 1;
|
||||
|
||||
debug2("%s: channel_new: %d linked to control channel %d",
|
||||
__func__, nc->self, nc->ctl_chan);
|
||||
|
||||
channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
|
||||
channel_register_cleanup(ssh, nc->self,
|
||||
mux_master_session_cleanup_cb, 1);
|
||||
|
||||
cctx = xcalloc(1, sizeof(*cctx));
|
||||
cctx->rid = rid;
|
||||
channel_register_open_confirm(nc->self, mux_stdio_confirm, cctx);
|
||||
channel_register_open_confirm(ssh, nc->self, mux_stdio_confirm, cctx);
|
||||
c->mux_pause = 1; /* stop handling messages until open_confirm done */
|
||||
|
||||
/* reply is deferred, sent by mux_session_confirm */
|
||||
@ -1040,7 +1066,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
|
||||
/* Callback on open confirmation in mux master for a mux stdio fwd session. */
|
||||
static void
|
||||
mux_stdio_confirm(int id, int success, void *arg)
|
||||
mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
|
||||
{
|
||||
struct mux_stdio_confirm_ctx *cctx = arg;
|
||||
Channel *c, *cc;
|
||||
@ -1048,9 +1074,9 @@ mux_stdio_confirm(int id, int success, void *arg)
|
||||
|
||||
if (cctx == NULL)
|
||||
fatal("%s: cctx == NULL", __func__);
|
||||
if ((c = channel_by_id(id)) == NULL)
|
||||
if ((c = channel_by_id(ssh, id)) == NULL)
|
||||
fatal("%s: no channel for id %d", __func__, id);
|
||||
if ((cc = channel_by_id(c->ctl_chan)) == NULL)
|
||||
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
|
||||
fatal("%s: channel %d lacks control channel %d", __func__,
|
||||
id, c->ctl_chan);
|
||||
|
||||
@ -1073,7 +1099,7 @@ mux_stdio_confirm(int id, int success, void *arg)
|
||||
|
||||
done:
|
||||
/* Send reply */
|
||||
buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply));
|
||||
buffer_put_string(cc->output, buffer_ptr(&reply), buffer_len(&reply));
|
||||
buffer_free(&reply);
|
||||
|
||||
if (cc->mux_pause <= 0)
|
||||
@ -1084,7 +1110,8 @@ mux_stdio_confirm(int id, int success, void *arg)
|
||||
}
|
||||
|
||||
static int
|
||||
process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
process_mux_stop_listening(struct ssh *ssh, u_int rid,
|
||||
Channel *c, Buffer *m, Buffer *r)
|
||||
{
|
||||
debug("%s: channel %d: stop listening", __func__, c->self);
|
||||
|
||||
@ -1101,7 +1128,7 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
}
|
||||
|
||||
if (mux_listener_channel != NULL) {
|
||||
channel_free(mux_listener_channel);
|
||||
channel_free(ssh, mux_listener_channel);
|
||||
client_stop_mux();
|
||||
free(options.control_path);
|
||||
options.control_path = NULL;
|
||||
@ -1117,7 +1144,8 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
}
|
||||
|
||||
static int
|
||||
process_mux_proxy(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
process_mux_proxy(struct ssh *ssh, u_int rid,
|
||||
Channel *c, Buffer *m, Buffer *r)
|
||||
{
|
||||
debug("%s: channel %d: proxy request", __func__, c->self);
|
||||
|
||||
@ -1130,7 +1158,7 @@ process_mux_proxy(u_int rid, Channel *c, Buffer *m, Buffer *r)
|
||||
|
||||
/* Channel callbacks fired on read/write from mux slave fd */
|
||||
static int
|
||||
mux_master_read_cb(Channel *c)
|
||||
mux_master_read_cb(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
|
||||
Buffer in, out;
|
||||
@ -1142,7 +1170,7 @@ mux_master_read_cb(Channel *c)
|
||||
if (c->mux_ctx == NULL) {
|
||||
state = xcalloc(1, sizeof(*state));
|
||||
c->mux_ctx = state;
|
||||
channel_register_cleanup(c->self,
|
||||
channel_register_cleanup(ssh, c->self,
|
||||
mux_master_control_cleanup_cb, 0);
|
||||
|
||||
/* Send hello */
|
||||
@ -1150,7 +1178,7 @@ mux_master_read_cb(Channel *c)
|
||||
buffer_put_int(&out, MUX_MSG_HELLO);
|
||||
buffer_put_int(&out, SSHMUX_VER);
|
||||
/* no extensions */
|
||||
buffer_put_string(&c->output, buffer_ptr(&out),
|
||||
buffer_put_string(c->output, buffer_ptr(&out),
|
||||
buffer_len(&out));
|
||||
buffer_free(&out);
|
||||
debug3("%s: channel %d: hello sent", __func__, c->self);
|
||||
@ -1161,7 +1189,7 @@ mux_master_read_cb(Channel *c)
|
||||
buffer_init(&out);
|
||||
|
||||
/* Channel code ensures that we receive whole packets */
|
||||
if ((ptr = buffer_get_string_ptr_ret(&c->input, &have)) == NULL) {
|
||||
if ((ptr = buffer_get_string_ptr_ret(c->input, &have)) == NULL) {
|
||||
malf:
|
||||
error("%s: malformed message", __func__);
|
||||
goto out;
|
||||
@ -1187,7 +1215,8 @@ mux_master_read_cb(Channel *c)
|
||||
|
||||
for (i = 0; mux_master_handlers[i].handler != NULL; i++) {
|
||||
if (type == mux_master_handlers[i].type) {
|
||||
ret = mux_master_handlers[i].handler(rid, c, &in, &out);
|
||||
ret = mux_master_handlers[i].handler(ssh, rid,
|
||||
c, &in, &out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1200,7 +1229,7 @@ mux_master_read_cb(Channel *c)
|
||||
}
|
||||
/* Enqueue reply packet */
|
||||
if (buffer_len(&out) != 0) {
|
||||
buffer_put_string(&c->output, buffer_ptr(&out),
|
||||
buffer_put_string(c->output, buffer_ptr(&out),
|
||||
buffer_len(&out));
|
||||
}
|
||||
out:
|
||||
@ -1210,7 +1239,7 @@ mux_master_read_cb(Channel *c)
|
||||
}
|
||||
|
||||
void
|
||||
mux_exit_message(Channel *c, int exitval)
|
||||
mux_exit_message(struct ssh *ssh, Channel *c, int exitval)
|
||||
{
|
||||
Buffer m;
|
||||
Channel *mux_chan;
|
||||
@ -1218,7 +1247,7 @@ mux_exit_message(Channel *c, int exitval)
|
||||
debug3("%s: channel %d: exit message, exitval %d", __func__, c->self,
|
||||
exitval);
|
||||
|
||||
if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
|
||||
if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
|
||||
fatal("%s: channel %d missing mux channel %d",
|
||||
__func__, c->self, c->ctl_chan);
|
||||
|
||||
@ -1228,19 +1257,19 @@ mux_exit_message(Channel *c, int exitval)
|
||||
buffer_put_int(&m, c->self);
|
||||
buffer_put_int(&m, exitval);
|
||||
|
||||
buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m));
|
||||
buffer_put_string(mux_chan->output, buffer_ptr(&m), buffer_len(&m));
|
||||
buffer_free(&m);
|
||||
}
|
||||
|
||||
void
|
||||
mux_tty_alloc_failed(Channel *c)
|
||||
mux_tty_alloc_failed(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
Buffer m;
|
||||
Channel *mux_chan;
|
||||
|
||||
debug3("%s: channel %d: TTY alloc failed", __func__, c->self);
|
||||
|
||||
if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
|
||||
if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
|
||||
fatal("%s: channel %d missing mux channel %d",
|
||||
__func__, c->self, c->ctl_chan);
|
||||
|
||||
@ -1249,13 +1278,13 @@ mux_tty_alloc_failed(Channel *c)
|
||||
buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL);
|
||||
buffer_put_int(&m, c->self);
|
||||
|
||||
buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m));
|
||||
buffer_put_string(mux_chan->output, buffer_ptr(&m), buffer_len(&m));
|
||||
buffer_free(&m);
|
||||
}
|
||||
|
||||
/* Prepare a mux master to listen on a Unix domain socket. */
|
||||
void
|
||||
muxserver_listen(void)
|
||||
muxserver_listen(struct ssh *ssh)
|
||||
{
|
||||
mode_t old_umask;
|
||||
char *orig_control_path = options.control_path;
|
||||
@ -1328,7 +1357,7 @@ muxserver_listen(void)
|
||||
|
||||
set_nonblock(muxserver_sock);
|
||||
|
||||
mux_listener_channel = channel_new("mux listener",
|
||||
mux_listener_channel = channel_new(ssh, "mux listener",
|
||||
SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1,
|
||||
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
|
||||
0, options.control_path, 1);
|
||||
@ -1339,7 +1368,7 @@ muxserver_listen(void)
|
||||
|
||||
/* Callback on open confirmation in mux master for a mux client session. */
|
||||
static void
|
||||
mux_session_confirm(int id, int success, void *arg)
|
||||
mux_session_confirm(struct ssh *ssh, int id, int success, void *arg)
|
||||
{
|
||||
struct mux_session_confirm_ctx *cctx = arg;
|
||||
const char *display;
|
||||
@ -1349,9 +1378,9 @@ mux_session_confirm(int id, int success, void *arg)
|
||||
|
||||
if (cctx == NULL)
|
||||
fatal("%s: cctx == NULL", __func__);
|
||||
if ((c = channel_by_id(id)) == NULL)
|
||||
if ((c = channel_by_id(ssh, id)) == NULL)
|
||||
fatal("%s: no channel for id %d", __func__, id);
|
||||
if ((cc = channel_by_id(c->ctl_chan)) == NULL)
|
||||
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
|
||||
fatal("%s: channel %d lacks control channel %d", __func__,
|
||||
id, c->ctl_chan);
|
||||
|
||||
@ -1370,27 +1399,27 @@ mux_session_confirm(int id, int success, void *arg)
|
||||
char *proto, *data;
|
||||
|
||||
/* Get reasonable local authentication information. */
|
||||
if (client_x11_get_proto(display, options.xauth_location,
|
||||
if (client_x11_get_proto(ssh, display, options.xauth_location,
|
||||
options.forward_x11_trusted, options.forward_x11_timeout,
|
||||
&proto, &data) == 0) {
|
||||
/* Request forwarding with authentication spoofing. */
|
||||
debug("Requesting X11 forwarding with authentication "
|
||||
"spoofing.");
|
||||
x11_request_forwarding_with_spoofing(id, display, proto,
|
||||
data, 1);
|
||||
x11_request_forwarding_with_spoofing(ssh, id,
|
||||
display, proto, data, 1);
|
||||
/* XXX exit_on_forward_failure */
|
||||
client_expect_confirm(id, "X11 forwarding",
|
||||
client_expect_confirm(ssh, id, "X11 forwarding",
|
||||
CONFIRM_WARN);
|
||||
}
|
||||
}
|
||||
|
||||
if (cctx->want_agent_fwd && options.forward_agent) {
|
||||
debug("Requesting authentication agent forwarding.");
|
||||
channel_request_start(id, "auth-agent-req@openssh.com", 0);
|
||||
channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0);
|
||||
packet_send();
|
||||
}
|
||||
|
||||
client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
|
||||
client_session2_setup(ssh, id, cctx->want_tty, cctx->want_subsys,
|
||||
cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env);
|
||||
|
||||
debug3("%s: sending success reply", __func__);
|
||||
@ -1402,7 +1431,7 @@ mux_session_confirm(int id, int success, void *arg)
|
||||
|
||||
done:
|
||||
/* Send reply */
|
||||
buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply));
|
||||
buffer_put_string(cc->output, buffer_ptr(&reply), buffer_len(&reply));
|
||||
buffer_free(&reply);
|
||||
|
||||
if (cc->mux_pause <= 0)
|
||||
@ -1571,31 +1600,38 @@ mux_client_hello_exchange(int fd)
|
||||
{
|
||||
Buffer m;
|
||||
u_int type, ver;
|
||||
int ret = -1;
|
||||
|
||||
buffer_init(&m);
|
||||
buffer_put_int(&m, MUX_MSG_HELLO);
|
||||
buffer_put_int(&m, SSHMUX_VER);
|
||||
/* no extensions */
|
||||
|
||||
if (mux_client_write_packet(fd, &m) != 0)
|
||||
fatal("%s: write packet: %s", __func__, strerror(errno));
|
||||
if (mux_client_write_packet(fd, &m) != 0) {
|
||||
debug("%s: write packet: %s", __func__, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
buffer_clear(&m);
|
||||
|
||||
/* Read their HELLO */
|
||||
if (mux_client_read_packet(fd, &m) != 0) {
|
||||
buffer_free(&m);
|
||||
return -1;
|
||||
debug("%s: read packet failed", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
type = buffer_get_int(&m);
|
||||
if (type != MUX_MSG_HELLO)
|
||||
fatal("%s: expected HELLO (%u) received %u",
|
||||
if (type != MUX_MSG_HELLO) {
|
||||
error("%s: expected HELLO (%u) received %u",
|
||||
__func__, MUX_MSG_HELLO, type);
|
||||
goto out;
|
||||
}
|
||||
ver = buffer_get_int(&m);
|
||||
if (ver != SSHMUX_VER)
|
||||
fatal("Unsupported multiplexing protocol version %d "
|
||||
if (ver != SSHMUX_VER) {
|
||||
error("Unsupported multiplexing protocol version %d "
|
||||
"(expected %d)", ver, SSHMUX_VER);
|
||||
goto out;
|
||||
}
|
||||
debug2("%s: master version %u", __func__, ver);
|
||||
/* No extensions are presently defined */
|
||||
while (buffer_len(&m) > 0) {
|
||||
@ -1606,8 +1642,11 @@ mux_client_hello_exchange(int fd)
|
||||
free(name);
|
||||
free(value);
|
||||
}
|
||||
/* success */
|
||||
ret = 0;
|
||||
out:
|
||||
buffer_free(&m);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u_int
|
||||
@ -1963,7 +2002,7 @@ mux_client_request_session(int fd)
|
||||
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
|
||||
|
||||
if (muxclient_terminate) {
|
||||
debug2("Exiting on signal %ld", (long)muxclient_terminate);
|
||||
debug2("Exiting on signal: %s", strsignal(muxclient_terminate));
|
||||
exitval = 255;
|
||||
} else if (!exitval_seen) {
|
||||
debug2("Control master terminated unexpectedly");
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: myproposal.h,v 1.54 2016/09/28 16:33:07 djm Exp $ */
|
||||
/* $OpenBSD: myproposal.h,v 1.55 2017/05/07 23:13:42 djm Exp $ */
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: nchan.c,v 1.63 2010/01/26 01:28:35 djm Exp $ */
|
||||
/* $OpenBSD: nchan.c,v 1.67 2017/09/12 06:35:32 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -33,9 +33,9 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
#include "ssh1.h"
|
||||
#include "ssh2.h"
|
||||
#include "buffer.h"
|
||||
#include "sshbuf.h"
|
||||
#include "ssherr.h"
|
||||
#include "packet.h"
|
||||
#include "channels.h"
|
||||
#include "compat.h"
|
||||
@ -74,18 +74,15 @@
|
||||
/*
|
||||
* ACTIONS: should never update the channel states
|
||||
*/
|
||||
static void chan_send_ieof1(Channel *);
|
||||
static void chan_send_oclose1(Channel *);
|
||||
static void chan_send_close2(Channel *);
|
||||
static void chan_send_eof2(Channel *);
|
||||
static void chan_send_eow2(Channel *);
|
||||
static void chan_send_eof2(struct ssh *, Channel *);
|
||||
static void chan_send_eow2(struct ssh *, Channel *);
|
||||
|
||||
/* helper */
|
||||
static void chan_shutdown_write(Channel *);
|
||||
static void chan_shutdown_read(Channel *);
|
||||
static void chan_shutdown_write(struct ssh *, Channel *);
|
||||
static void chan_shutdown_read(struct ssh *, Channel *);
|
||||
|
||||
static char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
|
||||
static char *istates[] = { "open", "drain", "wait_oclose", "closed" };
|
||||
static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
|
||||
static const char *istates[] = { "open", "drain", "wait_oclose", "closed" };
|
||||
|
||||
static void
|
||||
chan_set_istate(Channel *c, u_int next)
|
||||
@ -96,6 +93,7 @@ chan_set_istate(Channel *c, u_int next)
|
||||
istates[next]);
|
||||
c->istate = next;
|
||||
}
|
||||
|
||||
static void
|
||||
chan_set_ostate(Channel *c, u_int next)
|
||||
{
|
||||
@ -106,41 +104,13 @@ chan_set_ostate(Channel *c, u_int next)
|
||||
c->ostate = next;
|
||||
}
|
||||
|
||||
/*
|
||||
* SSH1 specific implementation of event functions
|
||||
*/
|
||||
|
||||
static void
|
||||
chan_rcvd_oclose1(Channel *c)
|
||||
{
|
||||
debug2("channel %d: rcvd oclose", c->self);
|
||||
switch (c->istate) {
|
||||
case CHAN_INPUT_WAIT_OCLOSE:
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
break;
|
||||
case CHAN_INPUT_OPEN:
|
||||
chan_shutdown_read(c);
|
||||
chan_send_ieof1(c);
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
break;
|
||||
case CHAN_INPUT_WAIT_DRAIN:
|
||||
/* both local read_failed and remote write_failed */
|
||||
chan_send_ieof1(c);
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
break;
|
||||
default:
|
||||
error("channel %d: protocol error: rcvd_oclose for istate %d",
|
||||
c->self, c->istate);
|
||||
return;
|
||||
}
|
||||
}
|
||||
void
|
||||
chan_read_failed(Channel *c)
|
||||
chan_read_failed(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
debug2("channel %d: read failed", c->self);
|
||||
switch (c->istate) {
|
||||
case CHAN_INPUT_OPEN:
|
||||
chan_shutdown_read(c);
|
||||
chan_shutdown_read(ssh, c);
|
||||
chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN);
|
||||
break;
|
||||
default:
|
||||
@ -149,25 +119,21 @@ chan_read_failed(Channel *c)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
chan_ibuf_empty(Channel *c)
|
||||
chan_ibuf_empty(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
debug2("channel %d: ibuf empty", c->self);
|
||||
if (buffer_len(&c->input)) {
|
||||
if (sshbuf_len(c->input)) {
|
||||
error("channel %d: chan_ibuf_empty for non empty buffer",
|
||||
c->self);
|
||||
return;
|
||||
}
|
||||
switch (c->istate) {
|
||||
case CHAN_INPUT_WAIT_DRAIN:
|
||||
if (compat20) {
|
||||
if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
|
||||
chan_send_eof2(c);
|
||||
chan_send_eof2(ssh, c);
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
} else {
|
||||
chan_send_ieof1(c);
|
||||
chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error("channel %d: chan_ibuf_empty for istate %d",
|
||||
@ -175,58 +141,19 @@ chan_ibuf_empty(Channel *c)
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
chan_rcvd_ieof1(Channel *c)
|
||||
{
|
||||
debug2("channel %d: rcvd ieof", c->self);
|
||||
switch (c->ostate) {
|
||||
case CHAN_OUTPUT_OPEN:
|
||||
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
|
||||
break;
|
||||
case CHAN_OUTPUT_WAIT_IEOF:
|
||||
chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
|
||||
break;
|
||||
default:
|
||||
error("channel %d: protocol error: rcvd_ieof for ostate %d",
|
||||
c->self, c->ostate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
chan_write_failed1(Channel *c)
|
||||
{
|
||||
debug2("channel %d: write failed", c->self);
|
||||
switch (c->ostate) {
|
||||
case CHAN_OUTPUT_OPEN:
|
||||
chan_shutdown_write(c);
|
||||
chan_send_oclose1(c);
|
||||
chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF);
|
||||
break;
|
||||
case CHAN_OUTPUT_WAIT_DRAIN:
|
||||
chan_shutdown_write(c);
|
||||
chan_send_oclose1(c);
|
||||
chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
|
||||
break;
|
||||
default:
|
||||
error("channel %d: chan_write_failed for ostate %d",
|
||||
c->self, c->ostate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
chan_obuf_empty(Channel *c)
|
||||
chan_obuf_empty(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
debug2("channel %d: obuf empty", c->self);
|
||||
if (buffer_len(&c->output)) {
|
||||
if (sshbuf_len(c->output)) {
|
||||
error("channel %d: chan_obuf_empty for non empty buffer",
|
||||
c->self);
|
||||
return;
|
||||
}
|
||||
switch (c->ostate) {
|
||||
case CHAN_OUTPUT_WAIT_DRAIN:
|
||||
chan_shutdown_write(c);
|
||||
if (!compat20)
|
||||
chan_send_oclose1(c);
|
||||
chan_shutdown_write(ssh, c);
|
||||
chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
|
||||
break;
|
||||
default:
|
||||
@ -235,47 +162,107 @@ chan_obuf_empty(Channel *c)
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
chan_send_ieof1(Channel *c)
|
||||
|
||||
void
|
||||
chan_rcvd_eow(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
debug2("channel %d: send ieof", c->self);
|
||||
debug2("channel %d: rcvd eow", 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: cannot send ieof for istate %d",
|
||||
c->self, c->istate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
chan_send_oclose1(Channel *c)
|
||||
{
|
||||
debug2("channel %d: send oclose", c->self);
|
||||
switch (c->ostate) {
|
||||
case CHAN_OUTPUT_OPEN:
|
||||
case CHAN_OUTPUT_WAIT_DRAIN:
|
||||
buffer_clear(&c->output);
|
||||
packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
|
||||
packet_put_int(c->remote_id);
|
||||
packet_send();
|
||||
break;
|
||||
default:
|
||||
error("channel %d: cannot send oclose for ostate %d",
|
||||
c->self, c->ostate);
|
||||
chan_shutdown_read(ssh, c);
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* the same for SSH2
|
||||
*/
|
||||
static void
|
||||
chan_rcvd_close2(Channel *c)
|
||||
chan_send_eof2(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
int r;
|
||||
|
||||
debug2("channel %d: send eof", c->self);
|
||||
switch (c->istate) {
|
||||
case CHAN_INPUT_WAIT_DRAIN:
|
||||
if (!c->have_remote_id)
|
||||
fatal("%s: channel %d: no remote_id",
|
||||
__func__, c->self);
|
||||
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EOF)) != 0 ||
|
||||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
|
||||
(r = sshpkt_send(ssh)) != 0)
|
||||
fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r));
|
||||
c->flags |= CHAN_EOF_SENT;
|
||||
break;
|
||||
default:
|
||||
error("channel %d: cannot send eof for istate %d",
|
||||
c->self, c->istate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
chan_send_close2(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
int r;
|
||||
|
||||
debug2("channel %d: send close", c->self);
|
||||
if (c->ostate != CHAN_OUTPUT_CLOSED ||
|
||||
c->istate != CHAN_INPUT_CLOSED) {
|
||||
error("channel %d: cannot send close for istate/ostate %d/%d",
|
||||
c->self, c->istate, c->ostate);
|
||||
} else if (c->flags & CHAN_CLOSE_SENT) {
|
||||
error("channel %d: already sent close", c->self);
|
||||
} else {
|
||||
if (!c->have_remote_id)
|
||||
fatal("%s: channel %d: no remote_id",
|
||||
__func__, c->self);
|
||||
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_CLOSE)) != 0 ||
|
||||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
|
||||
(r = sshpkt_send(ssh)) != 0)
|
||||
fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r));
|
||||
c->flags |= CHAN_CLOSE_SENT;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
chan_send_eow2(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
int r;
|
||||
|
||||
debug2("channel %d: send eow", c->self);
|
||||
if (c->ostate == CHAN_OUTPUT_CLOSED) {
|
||||
error("channel %d: must not sent eow on closed output",
|
||||
c->self);
|
||||
return;
|
||||
}
|
||||
if (!(datafellows & SSH_NEW_OPENSSH))
|
||||
return;
|
||||
if (!c->have_remote_id)
|
||||
fatal("%s: channel %d: no remote_id", __func__, c->self);
|
||||
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 ||
|
||||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
|
||||
(r = sshpkt_put_cstring(ssh, "eow@openssh.com")) != 0 ||
|
||||
(r = sshpkt_put_u8(ssh, 0)) != 0 ||
|
||||
(r = sshpkt_send(ssh)) != 0)
|
||||
fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
/* shared */
|
||||
|
||||
void
|
||||
chan_rcvd_ieof(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
debug2("channel %d: rcvd eof", c->self);
|
||||
c->flags |= CHAN_EOF_RCVD;
|
||||
if (c->ostate == CHAN_OUTPUT_OPEN)
|
||||
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
|
||||
if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
|
||||
sshbuf_len(c->output) == 0 &&
|
||||
!CHANNEL_EFD_OUTPUT_ACTIVE(c))
|
||||
chan_obuf_empty(ssh, c);
|
||||
}
|
||||
|
||||
void
|
||||
chan_rcvd_oclose(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
debug2("channel %d: rcvd close", c->self);
|
||||
if (!(c->flags & CHAN_LOCAL)) {
|
||||
@ -301,46 +288,27 @@ chan_rcvd_close2(Channel *c)
|
||||
}
|
||||
switch (c->istate) {
|
||||
case CHAN_INPUT_OPEN:
|
||||
chan_shutdown_read(c);
|
||||
chan_shutdown_read(ssh, c);
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
break;
|
||||
case CHAN_INPUT_WAIT_DRAIN:
|
||||
if (!(c->flags & CHAN_LOCAL))
|
||||
chan_send_eof2(c);
|
||||
chan_send_eof2(ssh, c);
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
chan_rcvd_eow(Channel *c)
|
||||
{
|
||||
debug2("channel %d: rcvd eow", c->self);
|
||||
switch (c->istate) {
|
||||
case CHAN_INPUT_OPEN:
|
||||
chan_shutdown_read(c);
|
||||
chan_set_istate(c, CHAN_INPUT_CLOSED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
chan_rcvd_eof2(Channel *c)
|
||||
{
|
||||
debug2("channel %d: rcvd eof", c->self);
|
||||
c->flags |= CHAN_EOF_RCVD;
|
||||
if (c->ostate == CHAN_OUTPUT_OPEN)
|
||||
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
|
||||
}
|
||||
static void
|
||||
chan_write_failed2(Channel *c)
|
||||
chan_write_failed(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
debug2("channel %d: write failed", c->self);
|
||||
switch (c->ostate) {
|
||||
case CHAN_OUTPUT_OPEN:
|
||||
case CHAN_OUTPUT_WAIT_DRAIN:
|
||||
chan_shutdown_write(c);
|
||||
chan_shutdown_write(ssh, c);
|
||||
if (strcmp(c->ctype, "session") == 0)
|
||||
chan_send_eow2(c);
|
||||
chan_send_eow2(ssh, c);
|
||||
chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
|
||||
break;
|
||||
default:
|
||||
@ -349,97 +317,15 @@ chan_write_failed2(Channel *c)
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
chan_send_eof2(Channel *c)
|
||||
{
|
||||
debug2("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();
|
||||
c->flags |= CHAN_EOF_SENT;
|
||||
break;
|
||||
default:
|
||||
error("channel %d: cannot send eof for istate %d",
|
||||
c->self, c->istate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
chan_send_close2(Channel *c)
|
||||
{
|
||||
debug2("channel %d: send close", c->self);
|
||||
if (c->ostate != CHAN_OUTPUT_CLOSED ||
|
||||
c->istate != CHAN_INPUT_CLOSED) {
|
||||
error("channel %d: cannot send close for istate/ostate %d/%d",
|
||||
c->self, c->istate, c->ostate);
|
||||
} else if (c->flags & CHAN_CLOSE_SENT) {
|
||||
error("channel %d: 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_send_eow2(Channel *c)
|
||||
{
|
||||
debug2("channel %d: send eow", c->self);
|
||||
if (c->ostate == CHAN_OUTPUT_CLOSED) {
|
||||
error("channel %d: must not sent eow on closed output",
|
||||
c->self);
|
||||
return;
|
||||
}
|
||||
if (!(datafellows & SSH_NEW_OPENSSH))
|
||||
return;
|
||||
packet_start(SSH2_MSG_CHANNEL_REQUEST);
|
||||
packet_put_int(c->remote_id);
|
||||
packet_put_cstring("eow@openssh.com");
|
||||
packet_put_char(0);
|
||||
packet_send();
|
||||
}
|
||||
|
||||
/* shared */
|
||||
|
||||
void
|
||||
chan_rcvd_ieof(Channel *c)
|
||||
{
|
||||
if (compat20)
|
||||
chan_rcvd_eof2(c);
|
||||
else
|
||||
chan_rcvd_ieof1(c);
|
||||
if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
|
||||
buffer_len(&c->output) == 0 &&
|
||||
!CHANNEL_EFD_OUTPUT_ACTIVE(c))
|
||||
chan_obuf_empty(c);
|
||||
}
|
||||
void
|
||||
chan_rcvd_oclose(Channel *c)
|
||||
{
|
||||
if (compat20)
|
||||
chan_rcvd_close2(c);
|
||||
else
|
||||
chan_rcvd_oclose1(c);
|
||||
}
|
||||
void
|
||||
chan_write_failed(Channel *c)
|
||||
{
|
||||
if (compat20)
|
||||
chan_write_failed2(c);
|
||||
else
|
||||
chan_write_failed1(c);
|
||||
}
|
||||
|
||||
void
|
||||
chan_mark_dead(Channel *c)
|
||||
chan_mark_dead(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
c->type = SSH_CHANNEL_ZOMBIE;
|
||||
}
|
||||
|
||||
int
|
||||
chan_is_dead(Channel *c, int do_send)
|
||||
chan_is_dead(struct ssh *ssh, Channel *c, int do_send)
|
||||
{
|
||||
if (c->type == SSH_CHANNEL_ZOMBIE) {
|
||||
debug2("channel %d: zombie", c->self);
|
||||
@ -447,16 +333,12 @@ chan_is_dead(Channel *c, int do_send)
|
||||
}
|
||||
if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
|
||||
return 0;
|
||||
if (!compat20) {
|
||||
debug2("channel %d: is dead", c->self);
|
||||
return 1;
|
||||
}
|
||||
if ((datafellows & SSH_BUG_EXTEOF) &&
|
||||
c->extended_usage == CHAN_EXTENDED_WRITE &&
|
||||
c->efd != -1 &&
|
||||
buffer_len(&c->extended) > 0) {
|
||||
debug2("channel %d: active efd: %d len %d",
|
||||
c->self, c->efd, buffer_len(&c->extended));
|
||||
sshbuf_len(c->extended) > 0) {
|
||||
debug2("channel %d: active efd: %d len %zu",
|
||||
c->self, c->efd, sshbuf_len(c->extended));
|
||||
return 0;
|
||||
}
|
||||
if (c->flags & CHAN_LOCAL) {
|
||||
@ -465,7 +347,7 @@ chan_is_dead(Channel *c, int do_send)
|
||||
}
|
||||
if (!(c->flags & CHAN_CLOSE_SENT)) {
|
||||
if (do_send) {
|
||||
chan_send_close2(c);
|
||||
chan_send_close2(ssh, c);
|
||||
} else {
|
||||
/* channel would be dead if we sent a close */
|
||||
if (c->flags & CHAN_CLOSE_RCVD) {
|
||||
@ -485,10 +367,10 @@ chan_is_dead(Channel *c, int do_send)
|
||||
|
||||
/* helper */
|
||||
static void
|
||||
chan_shutdown_write(Channel *c)
|
||||
chan_shutdown_write(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
buffer_clear(&c->output);
|
||||
if (compat20 && c->type == SSH_CHANNEL_LARVAL)
|
||||
sshbuf_reset(c->output);
|
||||
if (c->type == SSH_CHANNEL_LARVAL)
|
||||
return;
|
||||
/* shutdown failure is allowed if write failed already */
|
||||
debug2("channel %d: close_write", c->self);
|
||||
@ -498,16 +380,17 @@ chan_shutdown_write(Channel *c)
|
||||
"shutdown() failed for fd %d: %.100s",
|
||||
c->self, c->sock, strerror(errno));
|
||||
} else {
|
||||
if (channel_close_fd(&c->wfd) < 0)
|
||||
if (channel_close_fd(ssh, &c->wfd) < 0)
|
||||
logit("channel %d: chan_shutdown_write: "
|
||||
"close() failed for fd %d: %.100s",
|
||||
c->self, c->wfd, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
chan_shutdown_read(Channel *c)
|
||||
chan_shutdown_read(struct ssh *ssh, Channel *c)
|
||||
{
|
||||
if (compat20 && c->type == SSH_CHANNEL_LARVAL)
|
||||
if (c->type == SSH_CHANNEL_LARVAL)
|
||||
return;
|
||||
debug2("channel %d: close_read", c->self);
|
||||
if (c->sock != -1) {
|
||||
@ -523,7 +406,7 @@ chan_shutdown_read(Channel *c)
|
||||
c->self, c->sock, c->istate, c->ostate,
|
||||
strerror(errno));
|
||||
} else {
|
||||
if (channel_close_fd(&c->rfd) < 0)
|
||||
if (channel_close_fd(ssh, &c->rfd) < 0)
|
||||
logit("channel %d: chan_shutdown_read: "
|
||||
"close() failed for fd %d: %.100s",
|
||||
c->self, c->rfd, strerror(errno));
|
||||
|
@ -74,16 +74,6 @@ ssh_packet_put_raw(struct ssh *ssh, const void *buf, u_int len)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
}
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
void
|
||||
ssh_packet_put_bignum(struct ssh *ssh, BIGNUM * value)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshpkt_put_bignum1(ssh, value)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
void
|
||||
@ -150,16 +140,6 @@ ssh_packet_get_int64(struct ssh *ssh)
|
||||
return val;
|
||||
}
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
void
|
||||
ssh_packet_get_bignum(struct ssh *ssh, BIGNUM * value)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshpkt_get_bignum1(ssh, value)) != 0)
|
||||
fatal("%s: %s", __func__, ssh_err(r));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
void
|
||||
|
@ -6,7 +6,6 @@ void ssh_packet_start(struct ssh *, u_char);
|
||||
void ssh_packet_put_char(struct ssh *, int ch);
|
||||
void ssh_packet_put_int(struct ssh *, u_int value);
|
||||
void ssh_packet_put_int64(struct ssh *, u_int64_t value);
|
||||
void ssh_packet_put_bignum(struct ssh *, BIGNUM * value);
|
||||
void ssh_packet_put_bignum2(struct ssh *, BIGNUM * value);
|
||||
void ssh_packet_put_ecpoint(struct ssh *, const EC_GROUP *, const EC_POINT *);
|
||||
void ssh_packet_put_string(struct ssh *, const void *buf, u_int len);
|
||||
@ -17,7 +16,6 @@ void ssh_packet_send(struct ssh *);
|
||||
u_int ssh_packet_get_char(struct ssh *);
|
||||
u_int ssh_packet_get_int(struct ssh *);
|
||||
u_int64_t ssh_packet_get_int64(struct ssh *);
|
||||
void ssh_packet_get_bignum(struct ssh *, BIGNUM * value);
|
||||
void ssh_packet_get_bignum2(struct ssh *, BIGNUM * value);
|
||||
void ssh_packet_get_ecpoint(struct ssh *, const EC_GROUP *, EC_POINT *);
|
||||
void *ssh_packet_get_string(struct ssh *, u_int *length_ptr);
|
||||
@ -62,8 +60,6 @@ void packet_read_expect(int expected_type);
|
||||
ssh_packet_get_protocol_flags(active_state)
|
||||
#define packet_start_compression(level) \
|
||||
ssh_packet_start_compression(active_state, (level))
|
||||
#define packet_set_encryption_key(key, keylen, number) \
|
||||
ssh_packet_set_encryption_key(active_state, (key), (keylen), (number))
|
||||
#define packet_start(type) \
|
||||
ssh_packet_start(active_state, (type))
|
||||
#define packet_put_char(value) \
|
||||
@ -78,8 +74,6 @@ void packet_read_expect(int expected_type);
|
||||
ssh_packet_put_cstring(active_state, (str))
|
||||
#define packet_put_raw(buf, len) \
|
||||
ssh_packet_put_raw(active_state, (buf), (len))
|
||||
#define packet_put_bignum(value) \
|
||||
ssh_packet_put_bignum(active_state, (value))
|
||||
#define packet_put_bignum2(value) \
|
||||
ssh_packet_put_bignum2(active_state, (value))
|
||||
#define packet_send() \
|
||||
@ -88,8 +82,6 @@ void packet_read_expect(int expected_type);
|
||||
ssh_packet_read(active_state)
|
||||
#define packet_get_int64() \
|
||||
ssh_packet_get_int64(active_state)
|
||||
#define packet_get_bignum(value) \
|
||||
ssh_packet_get_bignum(active_state, (value))
|
||||
#define packet_get_bignum2(value) \
|
||||
ssh_packet_get_bignum2(active_state, (value))
|
||||
#define packet_remaining() \
|
||||
@ -157,5 +149,7 @@ void packet_disconnect(const char *, ...)
|
||||
ssh_packet_set_mux(active_state)
|
||||
#define packet_get_mux() \
|
||||
ssh_packet_get_mux(active_state)
|
||||
#define packet_clear_keys() \
|
||||
ssh_packet_clear_keys(active_state)
|
||||
|
||||
#endif /* _OPACKET_H */
|
||||
|
@ -16,9 +16,9 @@ RANLIB=@RANLIB@
|
||||
INSTALL=@INSTALL@
|
||||
LDFLAGS=-L. @LDFLAGS@
|
||||
|
||||
OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o reallocarray.o realpath.o rresvport.o setenv.o setproctitle.o sha1.o sha2.o rmd160.o md5.o sigact.o strcasestr.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o
|
||||
OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o reallocarray.o realpath.o recallocarray.o rresvport.o setenv.o setproctitle.o sha1.o sha2.o rmd160.o md5.o sigact.o strcasestr.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o freezero.o
|
||||
|
||||
COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-err.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xcrypt.o kludge-fd_set.o
|
||||
COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-err.o bsd-getpagesize.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-malloc.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xcrypt.o kludge-fd_set.o
|
||||
|
||||
PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o
|
||||
|
||||
|
@ -27,6 +27,12 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef HAVE_ERR
|
||||
void
|
||||
err(int r, const char *fmt, ...)
|
||||
|
23
crypto/openssh/openbsd-compat/bsd-getpagesize.c
Normal file
23
crypto/openssh/openbsd-compat/bsd-getpagesize.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* Placed in the public domain */
|
||||
|
||||
#ifndef HAVE_GETPAGESIZE
|
||||
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
int
|
||||
getpagesize(void)
|
||||
{
|
||||
#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
|
||||
long r = sysconf(_SC_PAGESIZE);
|
||||
if (r > 0 && r < INT_MAX)
|
||||
return (int)r;
|
||||
#endif
|
||||
/*
|
||||
* This is at the lower end of common values and appropriate for
|
||||
* our current use of getpagesize() in recallocarray().
|
||||
*/
|
||||
return 4096;
|
||||
}
|
||||
|
||||
#endif /* HAVE_GETPAGESIZE */
|
55
crypto/openssh/openbsd-compat/bsd-malloc.c
Normal file
55
crypto/openssh/openbsd-compat/bsd-malloc.c
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Darren Tucker (dtucker at zip com au).
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#undef malloc
|
||||
#undef calloc
|
||||
#undef realloc
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(HAVE_MALLOC) && HAVE_MALLOC == 0
|
||||
void *
|
||||
rpl_malloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
return malloc(size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CALLOC) && HAVE_CALLOC == 0
|
||||
void *
|
||||
rpl_calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
if (nmemb == 0)
|
||||
nmemb = 1;
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
return calloc(nmemb, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_REALLOC) && HAVE_REALLOC == 0
|
||||
void *
|
||||
rpl_realloc(void *ptr, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
#endif
|
@ -104,6 +104,16 @@ const char *strerror(int e)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_STRSIGNAL)
|
||||
char *strsignal(int sig)
|
||||
{
|
||||
static char buf[16];
|
||||
|
||||
(void)snprintf(buf, sizeof(buf), "%d", sig);
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_UTIMES
|
||||
int utimes(char *filename, struct timeval *tvp)
|
||||
{
|
||||
|
@ -49,6 +49,10 @@ int setegid(uid_t);
|
||||
const char *strerror(int);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_STRSIGNAL)
|
||||
char *strsignal(int);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SETLINEBUF)
|
||||
#define setlinebuf(a) (setvbuf((a), NULL, _IOLBF, 0))
|
||||
#endif
|
||||
|
@ -20,6 +20,8 @@
|
||||
void
|
||||
explicit_bzero(void *p, size_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
return;
|
||||
(void)memset_s(p, n, 0, n);
|
||||
}
|
||||
|
||||
@ -34,6 +36,8 @@ static void (* volatile ssh_bzero)(void *, size_t) = bzero;
|
||||
void
|
||||
explicit_bzero(void *p, size_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
return;
|
||||
/*
|
||||
* clang -fsanitize=memory needs to intercept memset-like functions
|
||||
* to correctly detect memory initialisation. Make sure one is called
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: fmt_scaled.c,v 1.13 2017/03/11 23:37:23 djm Exp $ */
|
||||
/* $OpenBSD: fmt_scaled.c,v 1.16 2017/03/16 02:40:46 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved.
|
||||
@ -125,22 +125,30 @@ scan_scaled(char *scaled, long long *result)
|
||||
/* ignore extra fractional digits */
|
||||
continue;
|
||||
fract_digits++; /* for later scaling */
|
||||
if (fpart >= LLONG_MAX / 10) {
|
||||
if (fpart > LLONG_MAX / 10) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
fpart *= 10;
|
||||
if (i > LLONG_MAX - fpart) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
fpart += i;
|
||||
} else { /* normal digit */
|
||||
if (++ndigits >= MAX_DIGITS) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
if (whole >= LLONG_MAX / 10) {
|
||||
if (whole > LLONG_MAX / 10) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
whole *= 10;
|
||||
if (i > LLONG_MAX - whole) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
whole += i;
|
||||
}
|
||||
}
|
||||
@ -170,7 +178,9 @@ scan_scaled(char *scaled, long long *result)
|
||||
}
|
||||
scale_fact = scale_factors[i];
|
||||
|
||||
if (whole >= LLONG_MAX / scale_fact) {
|
||||
/* check for overflow and underflow after scaling */
|
||||
if (whole > LLONG_MAX / scale_fact ||
|
||||
whole < LLONG_MIN / scale_fact) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
29
crypto/openssh/openbsd-compat/freezero.c
Normal file
29
crypto/openssh/openbsd-compat/freezero.c
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#ifndef HAVE_FREEZERO
|
||||
|
||||
void
|
||||
freezero(void *ptr, size_t sz)
|
||||
{
|
||||
explicit_bzero(ptr, sz);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
#endif /* HAVE_FREEZERO */
|
||||
|
@ -60,6 +60,10 @@ int bindresvport_sa(int sd, struct sockaddr *sa);
|
||||
void closefrom(int);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETPAGESIZE
|
||||
int getpagesize(void);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETCWD
|
||||
char *getcwd(char *pt, size_t size);
|
||||
#endif
|
||||
@ -68,6 +72,10 @@ char *getcwd(char *pt, size_t size);
|
||||
void *reallocarray(void *, size_t, size_t);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RECALLOCARRAY
|
||||
void *recallocarray(void *, size_t, size_t, size_t);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH)
|
||||
/*
|
||||
* glibc's FORTIFY_SOURCE can redefine this and prevent us picking up the
|
||||
@ -296,6 +304,10 @@ int bcrypt_pbkdf(const char *, size_t, const u_int8_t *, size_t,
|
||||
void explicit_bzero(void *p, size_t n);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FREEZERO
|
||||
void freezero(void *, size_t);
|
||||
#endif
|
||||
|
||||
char *xcrypt(const char *password, const char *salt);
|
||||
char *shadow_pw(struct passwd *pw);
|
||||
|
||||
|
@ -199,84 +199,81 @@ sys_tun_open(int tun, int mode)
|
||||
*/
|
||||
|
||||
#if defined(SSH_TUN_FILTER)
|
||||
/*
|
||||
* The tunnel forwarding protocol prepends the address family of forwarded
|
||||
* IP packets using OpenBSD's numbers.
|
||||
*/
|
||||
#define OPENBSD_AF_INET 2
|
||||
#define OPENBSD_AF_INET6 24
|
||||
|
||||
int
|
||||
sys_tun_infilter(struct Channel *c, char *buf, int len)
|
||||
sys_tun_infilter(struct ssh *ssh, struct Channel *c, char *buf, int _len)
|
||||
{
|
||||
int r;
|
||||
size_t len;
|
||||
char *ptr = buf;
|
||||
#if defined(SSH_TUN_PREPEND_AF)
|
||||
char rbuf[CHAN_RBUF];
|
||||
struct ip *iph;
|
||||
struct ip iph;
|
||||
#endif
|
||||
u_int32_t *af;
|
||||
char *ptr = buf;
|
||||
int r;
|
||||
#if defined(SSH_TUN_PREPEND_AF) || defined(SSH_TUN_COMPAT_AF)
|
||||
u_int32_t af;
|
||||
#endif
|
||||
|
||||
/* XXX update channel input filter API to use unsigned length */
|
||||
if (_len < 0)
|
||||
return -1;
|
||||
len = _len;
|
||||
|
||||
#if defined(SSH_TUN_PREPEND_AF)
|
||||
if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af)))
|
||||
return (-1);
|
||||
ptr = (char *)&rbuf[0];
|
||||
bcopy(buf, ptr + sizeof(u_int32_t), len);
|
||||
len += sizeof(u_int32_t);
|
||||
af = (u_int32_t *)ptr;
|
||||
|
||||
iph = (struct ip *)(ptr + sizeof(u_int32_t));
|
||||
switch (iph->ip_v) {
|
||||
case 6:
|
||||
*af = AF_INET6;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
*af = AF_INET;
|
||||
break;
|
||||
}
|
||||
if (len <= sizeof(iph) || len > sizeof(rbuf) - 4)
|
||||
return -1;
|
||||
/* Determine address family from packet IP header. */
|
||||
memcpy(&iph, buf, sizeof(iph));
|
||||
af = iph.ip_v == 6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET;
|
||||
/* Prepend address family to packet using OpenBSD constants */
|
||||
memcpy(rbuf + 4, buf, len);
|
||||
len += 4;
|
||||
POKE_U32(rbuf, af);
|
||||
ptr = rbuf;
|
||||
#elif defined(SSH_TUN_COMPAT_AF)
|
||||
/* Convert existing address family header to OpenBSD value */
|
||||
if (len <= 4)
|
||||
return -1;
|
||||
af = PEEK_U32(buf);
|
||||
/* Put it back */
|
||||
POKE_U32(buf, af == AF_INET6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET);
|
||||
#endif
|
||||
|
||||
#if defined(SSH_TUN_COMPAT_AF)
|
||||
if (len < (int)sizeof(u_int32_t))
|
||||
return (-1);
|
||||
|
||||
af = (u_int32_t *)ptr;
|
||||
if (*af == htonl(AF_INET6))
|
||||
*af = htonl(OPENBSD_AF_INET6);
|
||||
else
|
||||
*af = htonl(OPENBSD_AF_INET);
|
||||
#endif
|
||||
|
||||
if ((r = sshbuf_put_string(&c->input, ptr, len)) != 0)
|
||||
if ((r = sshbuf_put_string(c->input, ptr, len)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
return (0);
|
||||
}
|
||||
|
||||
u_char *
|
||||
sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen)
|
||||
sys_tun_outfilter(struct ssh *ssh, struct Channel *c,
|
||||
u_char **data, size_t *dlen)
|
||||
{
|
||||
u_char *buf;
|
||||
u_int32_t *af;
|
||||
u_int32_t af;
|
||||
int r;
|
||||
size_t xxx_dlen;
|
||||
|
||||
/* XXX new API is incompatible with this signature. */
|
||||
if ((r = sshbuf_get_string(&c->output, data, &xxx_dlen)) != 0)
|
||||
if ((r = sshbuf_get_string(c->output, data, dlen)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
if (dlen != NULL)
|
||||
*dlen = xxx_dlen;
|
||||
if (*dlen < sizeof(*af))
|
||||
if (*dlen < sizeof(af))
|
||||
return (NULL);
|
||||
buf = *data;
|
||||
|
||||
#if defined(SSH_TUN_PREPEND_AF)
|
||||
*dlen -= sizeof(u_int32_t);
|
||||
buf = *data + sizeof(u_int32_t);
|
||||
/* skip address family */
|
||||
*dlen -= sizeof(af);
|
||||
buf = *data + sizeof(af);
|
||||
#elif defined(SSH_TUN_COMPAT_AF)
|
||||
af = ntohl(*(u_int32_t *)buf);
|
||||
if (*af == OPENBSD_AF_INET6)
|
||||
*af = htonl(AF_INET6);
|
||||
else
|
||||
*af = htonl(AF_INET);
|
||||
/* translate address family */
|
||||
af = (PEEK_U32(buf) == OPENBSD_AF_INET6) ? AF_INET6 : AF_INET;
|
||||
POKE_U32(buf, af);
|
||||
#endif
|
||||
|
||||
return (buf);
|
||||
}
|
||||
#endif /* SSH_TUN_FILTER */
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define _PORT_TUN_H
|
||||
|
||||
struct Channel;
|
||||
struct ssh;
|
||||
|
||||
#if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD)
|
||||
# define CUSTOM_SYS_TUN_OPEN
|
||||
@ -26,8 +27,8 @@ int sys_tun_open(int, int);
|
||||
|
||||
#if defined(SSH_TUN_COMPAT_AF) || defined(SSH_TUN_PREPEND_AF)
|
||||
# define SSH_TUN_FILTER
|
||||
int sys_tun_infilter(struct Channel *, char *, int);
|
||||
u_char *sys_tun_outfilter(struct Channel *, u_char **, u_int *);
|
||||
int sys_tun_infilter(struct ssh *, struct Channel *, char *, int);
|
||||
u_char *sys_tun_outfilter(struct ssh *, struct Channel *, u_char **, size_t *);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
90
crypto/openssh/openbsd-compat/recallocarray.c
Normal file
90
crypto/openssh/openbsd-compat/recallocarray.c
Normal file
@ -0,0 +1,90 @@
|
||||
/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */
|
||||
|
||||
#include "includes.h"
|
||||
#ifndef HAVE_RECALLOCARRAY
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
|
||||
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
|
||||
*/
|
||||
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
|
||||
|
||||
void *
|
||||
recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
|
||||
{
|
||||
size_t oldsize, newsize;
|
||||
void *newptr;
|
||||
|
||||
if (ptr == NULL)
|
||||
return calloc(newnmemb, size);
|
||||
|
||||
if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
|
||||
newnmemb > 0 && SIZE_MAX / newnmemb < size) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
newsize = newnmemb * size;
|
||||
|
||||
if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
|
||||
oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
oldsize = oldnmemb * size;
|
||||
|
||||
/*
|
||||
* Don't bother too much if we're shrinking just a bit,
|
||||
* we do not shrink for series of small steps, oh well.
|
||||
*/
|
||||
if (newsize <= oldsize) {
|
||||
size_t d = oldsize - newsize;
|
||||
|
||||
if (d < oldsize / 2 && d < (size_t)getpagesize()) {
|
||||
memset((char *)ptr + newsize, 0, d);
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
newptr = malloc(newsize);
|
||||
if (newptr == NULL)
|
||||
return NULL;
|
||||
|
||||
if (newsize > oldsize) {
|
||||
memcpy(newptr, ptr, oldsize);
|
||||
memset((char *)newptr + oldsize, 0, newsize - oldsize);
|
||||
} else
|
||||
memcpy(newptr, ptr, newsize);
|
||||
|
||||
explicit_bzero(ptr, oldsize);
|
||||
free(ptr);
|
||||
|
||||
return newptr;
|
||||
}
|
||||
/* DEF_WEAK(recallocarray); */
|
||||
|
||||
#endif /* HAVE_RECALLOCARRAY */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user