Vendor import of OpenSSH 7.6p1.

This commit is contained in:
des 2018-05-06 12:24:45 +00:00
parent 03c436e653
commit b976cff2b1
238 changed files with 10538 additions and 14624 deletions

28
.gitignore vendored Normal file
View 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

View File

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

5065
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@ -99,7 +99,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).

23
LICENCE
View File

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

View File

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

View File

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

View File

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

View File

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

10
README
View File

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

View File

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

View File

@ -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 **);

View File

@ -106,7 +106,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 */
@ -468,18 +467,16 @@ sshpam_thread(void *ctxtp)
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
if (compat20) {
if (!do_pam_account()) {
sshpam_err = PAM_ACCT_EXPIRED;
if (!do_pam_account()) {
sshpam_err = PAM_ACCT_EXPIRED;
goto auth_fail;
}
if (sshpam_authctxt->force_pwchange) {
sshpam_err = pam_chauthtok(sshpam_handle,
PAM_CHANGE_EXPIRED_AUTHTOK);
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
}
if (sshpam_authctxt->force_pwchange) {
sshpam_err = pam_chauthtok(sshpam_handle,
PAM_CHANGE_EXPIRED_AUTHTOK);
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
sshpam_password_change_required(0);
}
sshpam_password_change_required(0);
}
buffer_put_cstring(&buffer, "OK");
@ -929,6 +926,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)
{
@ -936,6 +954,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));
@ -1060,6 +1080,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)

165
auth.c
View File

@ -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.
*
@ -43,9 +43,6 @@
#ifdef USE_SHADOW
#include <shadow.h>
#endif
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
@ -267,21 +264,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
@ -290,7 +307,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;
@ -309,6 +327,11 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
else
authmsg = authenticated ? "Accepted" : "Failed";
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,
@ -317,10 +340,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 &&
@ -428,7 +451,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;
@ -472,98 +495,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)
@ -596,7 +527,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);
@ -635,6 +566,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);
@ -694,7 +627,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;

81
auth.h
View File

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

View File

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

View File

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

View File

@ -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);
}

View File

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

View File

@ -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);
}

View File

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

View File

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

173
auth2.c
View File

@ -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.
*
@ -30,6 +30,7 @@
#include <sys/uio.h>
#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
#include <stdarg.h>
#include <string.h>
@ -55,6 +56,7 @@
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "ssherr.h"
/* import */
extern ServerOptions options;
@ -87,8 +89,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 *);
@ -168,16 +170,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);
@ -190,7 +195,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 */
@ -210,10 +215,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;
@ -267,14 +271,15 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
authctxt->user, authctxt->service, user, service);
}
/* 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;
@ -282,9 +287,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);
@ -293,10 +298,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;
@ -325,6 +330,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;
@ -352,7 +361,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();
@ -622,4 +631,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));
}

174
authfd.c
View File

@ -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,25 +277,14 @@ 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)
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--;
continue;
} else
goto out;
#endif
break;
case 2:
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--;
continue;
} else
goto out;
}
break;
}
i++;
}
@ -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)

View File

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

View File

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

View File

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

42
bufbn.c
View File

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

View File

@ -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 *);

3891
channels.c

File diff suppressed because it is too large Load Diff

View File

@ -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 *,
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_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(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,
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 *);
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 *);
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

View File

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

View File

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

303
cipher.c
View File

@ -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,38 +468,26 @@ 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;
else if (evplen < 0)
return SSH_ERR_LIBCRYPTO_ERROR;
if ((u_int)evplen != len)
return SSH_ERR_INVALID_ARGUMENT;
#ifndef OPENSSL_HAVE_EVPCTR
if (c->evptype == evp_aes_128_ctr)
ssh_aes_ctr_iv(cc->evp, 0, iv, len);
else
#endif
if (cipher_authlen(c)) {
if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
len, iv))
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:
evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
if (evplen == 0)
return 0;
else if (evplen < 0)
return SSH_ERR_LIBCRYPTO_ERROR;
if ((u_int)evplen != len)
return SSH_ERR_INVALID_ARGUMENT;
}
#ifndef OPENSSL_HAVE_EVPCTR
if (c->evptype == evp_aes_128_ctr)
ssh_aes_ctr_iv(cc->evp, 0, iv, len);
else
#endif
if (cipher_authlen(c)) {
if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
len, iv))
return SSH_ERR_LIBCRYPTO_ERROR;
} else
memcpy(iv, cc->evp->iv, len);
#endif
return 0;
}
@ -651,36 +504,24 @@ 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;
evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
if (evplen <= 0)
return SSH_ERR_LIBCRYPTO_ERROR;
#ifndef OPENSSL_HAVE_EVPCTR
/* XXX iv arg is const, but ssh_aes_ctr_iv isn't */
if (c->evptype == evp_aes_128_ctr)
ssh_aes_ctr_iv(cc->evp, 1, (u_char *)iv, evplen);
else
/* XXX iv arg is const, but ssh_aes_ctr_iv isn't */
if (c->evptype == evp_aes_128_ctr)
ssh_aes_ctr_iv(cc->evp, 1, (u_char *)iv, evplen);
else
#endif
if (cipher_authlen(c)) {
/* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
if (!EVP_CIPHER_CTX_ctrl(cc->evp,
EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
return SSH_ERR_LIBCRYPTO_ERROR;
} else
memcpy(cc->evp->iv, iv, evplen);
break;
if (cipher_authlen(c)) {
/* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
if (!EVP_CIPHER_CTX_ctrl(cc->evp,
EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
return SSH_ERR_LIBCRYPTO_ERROR;
} else
memcpy(cc->evp->iv, iv, evplen);
#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;
}

View File

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

View File

@ -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 *);

View File

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

View File

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

View File

@ -252,6 +252,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. */
#undef HAVE_CAP_RIGHTS_LIMIT
@ -469,6 +472,9 @@
/* Define to 1 if you have the `freeaddrinfo' function. */
#undef HAVE_FREEADDRINFO
/* Define to 1 if you have the `freezero' function. */
#undef HAVE_FREEZERO
/* Define to 1 if the system has the type `fsblkcnt_t'. */
#undef HAVE_FSBLKCNT_T
@ -769,6 +775,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. */
#undef HAVE_MALLOC
/* Define to 1 if you have the `mblen' function. */
#undef HAVE_MBLEN
@ -899,12 +909,19 @@
/* Define to 1 if you have the <readpassphrase.h> header file. */
#undef HAVE_READPASSPHRASE_H
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
and to 0 otherwise. */
#undef HAVE_REALLOC
/* Define to 1 if you have the `reallocarray' function. */
#undef HAVE_REALLOCARRAY
/* Define to 1 if you have the `realpath' function. */
#undef HAVE_REALPATH
/* Define to 1 if you have the `recallocarray' function. */
#undef HAVE_RECALLOCARRAY
/* Define to 1 if you have the `recvmsg' function. */
#undef HAVE_RECVMSG
@ -1115,6 +1132,9 @@
/* Define to 1 if you have the `strsep' function. */
#undef HAVE_STRSEP
/* Define to 1 if you have the `strsignal' function. */
#undef HAVE_STRSIGNAL
/* Define to 1 if you have the `strtoll' function. */
#undef HAVE_STRTOLL
@ -1157,6 +1177,12 @@
/* Define to 1 if `st_blksize' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
/* Define to 1 if `st_mtim' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIM
/* Define to 1 if `st_mtime' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIME
/* Define to 1 if the system has the type `struct timespec'. */
#undef HAVE_STRUCT_TIMESPEC
@ -1181,8 +1207,8 @@
/* Define to 1 if you have the <sys/bsdtty.h> header file. */
#undef HAVE_SYS_BSDTTY_H
/* Define to 1 if you have the <sys/capability.h> header file. */
#undef HAVE_SYS_CAPABILITY_H
/* Define to 1 if you have the <sys/capsicum.h> header file. */
#undef HAVE_SYS_CAPSICUM_H
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#undef HAVE_SYS_CDEFS_H
@ -1719,9 +1745,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
@ -1760,11 +1783,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

335
configure vendored
View File

@ -624,7 +624,6 @@ ac_includes_default="\
#endif"
ac_subst_vars='LTLIBOBJS
LIBOBJS
UNSUPPORTED_ALGORITHMS
TEST_MALLOC_OPTIONS
TEST_SSH_UTF8
@ -648,7 +647,7 @@ TEST_SSH_ECC
LIBEDIT
PKGCONFIG
LDNSCONFIG
COMMENT_OUT_RSA1
LIBOBJS
LD
PATH_PASSWD_PROG
STARTUP_SCRIPT_SHELL
@ -735,13 +734,14 @@ ac_user_opts='
enable_option_checking
enable_largefile
with_openssl
with_ssh1
with_stackprotect
with_hardening
with_rpath
with_cflags
with_cflags_after
with_cppflags
with_ldflags
with_ldflags_after
with_libs
with_Werror
with_solaris_contracts
@ -1430,13 +1430,14 @@ Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL**
--with-ssh1 Enable support for SSH protocol 1
--without-stackprotect Don't use compiler's stack protection
--without-hardening Don't use toolchain hardening flags
--without-rpath Disable auto-added -R linker paths
--with-cflags Specify additional flags to pass to compiler
--with-cflags-after Specify additional flags to pass to compiler after configure
--with-cppflags Specify additional flags to pass to preprocessor
--with-ldflags Specify additional flags to pass to linker
--with-ldflags-after Specify additional flags to pass to linker after configure
--with-libs Specify additional libraries to link with
--with-Werror Build main code with -Werror
--with-solaris-contracts Enable Solaris process contracts (experimental)
@ -5634,14 +5635,11 @@ fi
openssl=yes
ssh1=no
COMMENT_OUT_RSA1="#no ssh1#"
# Check whether --with-openssl was given.
if test "${with_openssl+set}" = set; then :
withval=$with_openssl; if test "x$withval" = "xno" ; then
openssl=no
ssh1=no
fi
@ -5657,41 +5655,6 @@ cat >>confdefs.h <<_ACEOF
#define WITH_OPENSSL 1
_ACEOF
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Check whether --with-ssh1 was given.
if test "${with_ssh1+set}" = set; then :
withval=$with_ssh1;
if test "x$withval" = "xyes" ; then
if test "x$openssl" = "xno" ; then
as_fn_error $? "Cannot enable SSH protocol 1 with OpenSSL disabled" "$LINENO" 5
fi
ssh1=yes
COMMENT_OUT_RSA1=""
elif test "x$withval" = "xno" ; then
ssh1=no
else
as_fn_error $? "unknown --with-ssh1 argument" "$LINENO" 5
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether SSH protocol 1 support is enabled" >&5
$as_echo_n "checking whether SSH protocol 1 support is enabled... " >&6; }
if test "x$ssh1" = "xyes" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
cat >>confdefs.h <<_ACEOF
#define WITH_SSH1 1
_ACEOF
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
@ -5742,6 +5705,49 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CFLAGS="$saved_CFLAGS"
if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -pipe" >&5
$as_echo_n "checking if $CC supports compile flag -pipe... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -pipe"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-pipe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if `grep -i "unrecognized option" conftest.err >/dev/null`
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Qunused-arguments" >&5
$as_echo_n "checking if $CC supports compile flag -Qunused-arguments... " >&6; }
@ -6215,6 +6221,7 @@ $as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
if test "x$use_toolchain_hardening" = "x1"; then
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -D_FORTIFY_SOURCE=2" >&5
$as_echo_n "checking if $CC supports compile flag -D_FORTIFY_SOURCE=2... " >&6; }
@ -6258,7 +6265,6 @@ $as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
if test "x$use_toolchain_hardening" = "x1"; then
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,relro" >&5
$as_echo_n "checking if $LD supports link flag -Wl,-z,relro... " >&6; }
@ -6620,6 +6626,19 @@ if test "${with_cflags+set}" = set; then :
fi
# Check whether --with-cflags-after was given.
if test "${with_cflags_after+set}" = set; then :
withval=$with_cflags_after;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
CFLAGS_AFTER="$withval"
fi
fi
# Check whether --with-cppflags was given.
if test "${with_cppflags+set}" = set; then :
withval=$with_cppflags;
@ -6644,6 +6663,18 @@ if test "${with_ldflags+set}" = set; then :
fi
# Check whether --with-ldflags-after was given.
if test "${with_ldflags_after+set}" = set; then :
withval=$with_ldflags_after;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
LDFLAGS_AFTER="$withval"
fi
fi
# Check whether --with-libs was given.
if test "${with_libs+set}" = set; then :
withval=$with_libs;
@ -6712,7 +6743,6 @@ for ac_header in \
sys/audit.h \
sys/bitypes.h \
sys/bsdtty.h \
sys/capability.h \
sys/cdefs.h \
sys/dir.h \
sys/mman.h \
@ -6756,6 +6786,25 @@ fi
done
# sys/capsicum.h requires sys/types.h
for ac_header in sys/capsicum.h
do :
ac_fn_c_check_header_compile "$LINENO" "sys/capsicum.h" "ac_cv_header_sys_capsicum_h" "
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
"
if test "x$ac_cv_header_sys_capsicum_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_CAPSICUM_H 1
_ACEOF
fi
done
# lastlog.h requires sys/time.h to be included first on Solaris
for ac_header in lastlog.h
do :
@ -8208,6 +8257,8 @@ $as_echo "#define UNIXWARE_LONG_PASSWORDS 1" >>confdefs.h
$as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h
$as_echo "#define BROKEN_TCGETATTR_ICANON 1" >>confdefs.h
TEST_SHELL=$SHELL # let configure find us a capable shell
case "$host" in
*-*-sysv5SCO_SV*) # SCO OpenServer 6.x
@ -9631,6 +9682,8 @@ if test "$ac_res" != no; then :
fi
# "Particular Function Checks"
# see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html
for ac_func in strftime
do :
ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime"
@ -9686,6 +9739,149 @@ fi
fi
done
for ac_header in stdlib.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
if test "x$ac_cv_header_stdlib_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STDLIB_H 1
_ACEOF
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5
$as_echo_n "checking for GNU libc compatible malloc... " >&6; }
if ${ac_cv_func_malloc_0_nonnull+:} false; then :
$as_echo_n "(cached) " >&6
else
if test "$cross_compiling" = yes; then :
ac_cv_func_malloc_0_nonnull=no
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#if defined STDC_HEADERS || defined HAVE_STDLIB_H
# include <stdlib.h>
#else
char *malloc ();
#endif
int
main ()
{
return ! malloc (0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
ac_cv_func_malloc_0_nonnull=yes
else
ac_cv_func_malloc_0_nonnull=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5
$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; }
if test $ac_cv_func_malloc_0_nonnull = yes; then :
$as_echo "#define HAVE_MALLOC 1" >>confdefs.h
else
$as_echo "#define HAVE_MALLOC 0" >>confdefs.h
case " $LIBOBJS " in
*" malloc.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS malloc.$ac_objext"
;;
esac
$as_echo "#define malloc rpl_malloc" >>confdefs.h
fi
for ac_header in stdlib.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
if test "x$ac_cv_header_stdlib_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STDLIB_H 1
_ACEOF
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5
$as_echo_n "checking for GNU libc compatible realloc... " >&6; }
if ${ac_cv_func_realloc_0_nonnull+:} false; then :
$as_echo_n "(cached) " >&6
else
if test "$cross_compiling" = yes; then :
ac_cv_func_realloc_0_nonnull=no
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#if defined STDC_HEADERS || defined HAVE_STDLIB_H
# include <stdlib.h>
#else
char *realloc ();
#endif
int
main ()
{
return ! realloc (0, 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
ac_cv_func_realloc_0_nonnull=yes
else
ac_cv_func_realloc_0_nonnull=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5
$as_echo "$ac_cv_func_realloc_0_nonnull" >&6; }
if test $ac_cv_func_realloc_0_nonnull = yes; then :
$as_echo "#define HAVE_REALLOC 1" >>confdefs.h
else
$as_echo "#define HAVE_REALLOC 0" >>confdefs.h
case " $LIBOBJS " in
*" realloc.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS realloc.$ac_objext"
;;
esac
$as_echo "#define realloc rpl_realloc" >>confdefs.h
fi
# 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
$as_echo "#define HAVE_CALLOC 0" >>confdefs.h
$as_echo "#define calloc rpl_calloc" >>confdefs.h
fi
# Check for ALTDIRFUNC glob() extension
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLOB_ALTDIRFUNC support" >&5
@ -10068,6 +10264,7 @@ fi
else
LIBS="$LIBS `$LDNSCONFIG --libs`"
CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`"
ldns=yes
fi
elif test "x$withval" != "xno" ; then
CPPFLAGS="$CPPFLAGS -I${withval}/include"
@ -10647,6 +10844,7 @@ for ac_func in \
fchmod \
fchown \
freeaddrinfo \
freezero \
fstatfs \
fstatvfs \
futimes \
@ -10655,6 +10853,7 @@ for ac_func in \
getgrouplist \
getnameinfo \
getopt \
getpagesize \
getpeereid \
getpeerucred \
getpgid \
@ -10685,6 +10884,7 @@ for ac_func in \
readpassphrase \
reallocarray \
recvmsg \
recallocarray \
rresvport_af \
sendmsg \
setdtablesize \
@ -10718,6 +10918,7 @@ for ac_func in \
strnlen \
strnvis \
strptime \
strsignal \
strtonum \
strtoll \
strtoul \
@ -12484,7 +12685,11 @@ if ac_fn_c_try_run "$LINENO"; then :
10000*|0*)
as_fn_error $? "OpenSSL >= 1.0.1 required (have \"$ssl_library_ver\")" "$LINENO" 5
;;
*) ;;
100*) ;; # 1.0.x
200*) ;; # LibreSSL
*)
as_fn_error $? "OpenSSL >= 1.1.0 is not yet supported (have \"$ssl_library_ver\")" "$LINENO" 5
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_library_ver" >&5
$as_echo "$ssl_library_ver" >&6; }
@ -13053,9 +13258,6 @@ $as_echo_n "checking whether OpenSSL has NID_X9_62_prime256v1... " >&6; }
#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
int
main ()
@ -13091,9 +13293,6 @@ $as_echo_n "checking whether OpenSSL has NID_secp384r1... " >&6; }
#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
int
main ()
@ -13129,9 +13328,6 @@ $as_echo_n "checking whether OpenSSL has NID_secp521r1... " >&6; }
#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
int
main ()
@ -13858,6 +14054,7 @@ $as_echo_n "checking if select works with descriptor rlimit... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
select_works_with_rlimit=yes
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@ -13918,6 +14115,7 @@ $as_echo_n "checking if setrlimit(RLIMIT_NOFILE,{0,0}) works... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
rlimit_nofile_zero_works=yes
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@ -14052,10 +14250,10 @@ $as_echo "#define SANDBOX_SECCOMP_FILTER 1" >>confdefs.h
elif test "x$sandbox_arg" = "xcapsicum" || \
( test -z "$sandbox_arg" && \
test "x$ac_cv_header_sys_capability_h" = "xyes" && \
test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \
test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then
test "x$ac_cv_header_sys_capability_h" != "xyes" && \
as_fn_error $? "capsicum sandbox requires sys/capability.h header" "$LINENO" 5
test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \
as_fn_error $? "capsicum sandbox requires sys/capsicum.h header" "$LINENO" 5
test "x$ac_cv_func_cap_rights_limit" != "xyes" && \
as_fn_error $? "capsicum sandbox requires cap_rights_limit function" "$LINENO" 5
SANDBOX_STYLE="capsicum"
@ -16185,6 +16383,26 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
fi
ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_mtim" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_STAT_ST_MTIM 1
_ACEOF
fi
ac_fn_c_check_member "$LINENO" "struct stat" "st_mtime" "ac_cv_member_struct_stat_st_mtime" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_mtime" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_STAT_ST_MTIME 1
_ACEOF
fi
ac_fn_c_check_member "$LINENO" "struct passwd" "pw_gecos" "ac_cv_member_struct_passwd_pw_gecos" "
@ -19055,6 +19273,9 @@ TEST_MALLOC_OPTIONS=$TEST_MALLOC_OPTIONS
UNSUPPORTED_ALGORITHMS=$unsupported_algorithms
CFLAGS="${CFLAGS} ${CFLAGS_AFTER}"
LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}"
ac_config_files="$ac_config_files Makefile buildpkg.sh opensshd.init openssh.xml openbsd-compat/Makefile openbsd-compat/regress/Makefile survey.sh"

View File

@ -109,13 +109,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
]
)
@ -127,31 +124,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],
@ -179,6 +151,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])
@ -190,8 +163,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])
@ -316,6 +289,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] ,
[
@ -334,6 +317,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],
[
@ -397,7 +389,6 @@ AC_CHECK_HEADERS([ \
sys/audit.h \
sys/bitypes.h \
sys/bsdtty.h \
sys/capability.h \
sys/cdefs.h \
sys/dir.h \
sys/mman.h \
@ -429,6 +420,13 @@ AC_CHECK_HEADERS([ \
wchar.h \
])
# sys/capsicum.h requires sys/types.h
AC_CHECK_HEADERS([sys/capsicum.h], [], [], [
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
])
# lastlog.h requires sys/time.h to be included first on Solaris
AC_CHECK_HEADERS([lastlog.h], [], [], [
#ifdef HAVE_SYS_TIME_H
@ -1007,6 +1005,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
@ -1332,7 +1331,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])
@ -1486,6 +1495,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"
@ -1696,6 +1706,7 @@ AC_CHECK_FUNCS([ \
fchmod \
fchown \
freeaddrinfo \
freezero \
fstatfs \
fstatvfs \
futimes \
@ -1704,6 +1715,7 @@ AC_CHECK_FUNCS([ \
getgrouplist \
getnameinfo \
getopt \
getpagesize \
getpeereid \
getpeerucred \
getpgid \
@ -1734,6 +1746,7 @@ AC_CHECK_FUNCS([ \
readpassphrase \
reallocarray \
recvmsg \
recallocarray \
rresvport_af \
sendmsg \
setdtablesize \
@ -1767,6 +1780,7 @@ AC_CHECK_FUNCS([ \
strnlen \
strnvis \
strptime \
strsignal \
strtonum \
strtoll \
strtoul \
@ -2535,7 +2549,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])
],
@ -2768,9 +2786,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 */
@ -2789,9 +2804,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 */
@ -2810,9 +2822,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 */
@ -3197,7 +3206,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])
@ -3223,7 +3233,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])
@ -3286,10 +3297,10 @@ elif test "x$sandbox_arg" = "xseccomp_filter" || \
AC_DEFINE([SANDBOX_SECCOMP_FILTER], [1], [Sandbox using seccomp filter])
elif test "x$sandbox_arg" = "xcapsicum" || \
( test -z "$sandbox_arg" && \
test "x$ac_cv_header_sys_capability_h" = "xyes" && \
test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \
test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then
test "x$ac_cv_header_sys_capability_h" != "xyes" && \
AC_MSG_ERROR([capsicum sandbox requires sys/capability.h header])
test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \
AC_MSG_ERROR([capsicum sandbox requires sys/capsicum.h header])
test "x$ac_cv_func_cap_rights_limit" != "xyes" && \
AC_MSG_ERROR([capsicum sandbox requires cap_rights_limit function])
SANDBOX_STYLE="capsicum"
@ -3845,6 +3856,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],
[], [], [[
@ -5044,6 +5057,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 \

View File

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

View File

@ -1,4 +1,4 @@
%define ver 7.5p1
%define ver 7.6p1
%define rel 1
# OpenSSH privilege separation requires a user & group ID

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
}

View File

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

2
dns.c
View File

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

2
dns.h
View File

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

View File

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

View File

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

View File

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

81
kex.c
View File

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

9
kex.h
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

177
key.c
View File

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

36
key.h
View File

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

4
krl.c
View File

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

35
log.c
View File

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

4
log.h
View File

@ -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 *);

9
mac.c
View File

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

View File

@ -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) */

473
misc.c
View File

@ -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,10 +29,16 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.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>
@ -61,6 +67,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 *
@ -539,7 +549,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;
@ -1085,6 +1095,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 },
@ -1274,3 +1285,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);
}

22
misc.h
View File

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

View File

@ -71,4 +71,4 @@ STANDARDS
the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006,
2006.
OpenBSD 6.0 September 26, 2012 OpenBSD 6.0
OpenBSD 6.2 September 26, 2012 OpenBSD 6.2

103
monitor.c
View File

@ -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);
}

View File

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

View File

@ -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*);

237
mux.c
View File

@ -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>
*
@ -161,22 +161,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 },
@ -193,52 +203,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. */
@ -266,7 +278,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;
@ -308,7 +321,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;
@ -401,7 +415,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);
@ -453,15 +467,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));
@ -470,17 +485,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);
@ -493,7 +510,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);
@ -582,7 +600,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;
@ -590,7 +608,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;
@ -616,7 +634,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);
@ -625,7 +643,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);
@ -651,7 +669,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);
@ -659,7 +677,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;
@ -727,13 +746,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;
}
@ -784,7 +806,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);
@ -798,7 +820,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);
@ -827,7 +849,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;
@ -908,11 +931,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";
}
@ -942,7 +965,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;
@ -986,7 +1010,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);
@ -1018,19 +1042,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 */
@ -1039,7 +1065,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;
@ -1047,9 +1073,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);
@ -1072,7 +1098,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)
@ -1083,7 +1109,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);
@ -1100,7 +1127,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;
@ -1116,7 +1143,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);
@ -1129,7 +1157,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;
@ -1141,7 +1169,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 */
@ -1149,7 +1177,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);
@ -1160,7 +1188,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;
@ -1186,7 +1214,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;
}
}
@ -1199,7 +1228,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:
@ -1209,7 +1238,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;
@ -1217,7 +1246,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);
@ -1227,19 +1256,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);
@ -1248,13 +1277,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;
@ -1327,7 +1356,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);
@ -1338,7 +1367,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;
@ -1348,9 +1377,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);
@ -1369,27 +1398,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__);
@ -1401,7 +1430,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)
@ -1570,31 +1599,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) {
@ -1605,8 +1641,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
@ -1962,7 +2001,7 @@ mux_client_request_session(int fd)
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
if (muxclient_terminate) {
debug2("Exiting on signal %d", muxclient_terminate);
debug2("Exiting on signal: %s", strsignal(muxclient_terminate));
exitval = 255;
} else if (!exitval_seen) {
debug2("Control master terminated unexpectedly");

View File

@ -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 $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -121,8 +121,7 @@
"aes128-ctr,aes192-ctr,aes256-ctr" \
AESGCM_CIPHER_MODES
#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT "," \
"aes128-cbc,aes192-cbc,aes256-cbc"
#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT
#define KEX_SERVER_MAC \
"umac-64-etm@openssh.com," \

385
nchan.c
View File

@ -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_set_istate(c, CHAN_INPUT_CLOSED);
} else {
chan_send_ieof1(c);
chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);
}
if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
chan_send_eof2(ssh, c);
chan_set_istate(c, CHAN_INPUT_CLOSED);
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));

View File

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

View File

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

View File

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

View File

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

View 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 */

View 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

View File

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

View File

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

View File

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

View File

@ -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
openbsd-compat/freezero.c Normal file
View 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 */

View File

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

View File

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

View File

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

View 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