Vendor import of OpenSSH 5.7p1

This commit is contained in:
des 2011-02-17 11:47:40 +00:00
parent a074372f88
commit e089765887
156 changed files with 7327 additions and 4480 deletions

3428
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@ -206,6 +206,7 @@ OpenSSH contains no GPL code.
Sun Microsystems
The SCO Group
Daniel Walsh
Red Hat, Inc
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions

View File

@ -1,4 +1,4 @@
# $Id: Makefile.in,v 1.310 2010/05/12 06:51:39 dtucker Exp $
# $Id: Makefile.in,v 1.320 2011/01/17 10:15:29 dtucker Exp $
# uncomment if you run a non bourne compatable shell. Ie. csh
#SHELL = @SH@
@ -58,6 +58,7 @@ ENT=@ENT@
XAUTH_PATH=@XAUTH_PATH@
LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
@ -71,26 +72,27 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
log.o match.o md-sha256.o moduli.o nchan.o packet.o \
readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
kexgex.o kexdhc.o kexgexc.o msg.o progressmeter.o dns.o \
entropy.o gss-genr.o umac.o jpake.o schnorr.o \
ssh-pkcs11.o
monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \
schnorr.o ssh-pkcs11.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
sshconnect.o sshconnect1.o sshconnect2.o mux.o \
roaming_common.o roaming_client.o
SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
audit.o audit-bsm.o audit-linux.o platform.o \
sshpty.o sshlogin.o servconf.o serverloop.o \
auth.o auth1.o auth2.o auth-options.o session.o \
auth-chall.o auth2-chall.o groupaccess.o \
auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \
monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \
auth-krb5.o \
auth2-gss.o gss-serv.o gss-serv-krb5.o \
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o \
sftp-server.o sftp-common.o \
roaming_common.o roaming_serv.o
MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
@ -108,6 +110,7 @@ PATHSUBS = \
-e 's|/usr/libexec|$(libexecdir)|g' \
-e 's|/etc/shosts.equiv|$(sysconfdir)/shosts.equiv|g' \
-e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \
-e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_key|g' \
-e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \
-e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \
-e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \
@ -230,7 +233,7 @@ catman-do:
@for f in $(MANPAGES_IN) ; do \
base=`echo $$f | sed 's/\..*$$//'` ; \
echo "$$f -> $$base.0" ; \
nroff -mandoc $$f | cat -v | sed -e 's/.\^H//g' \
$(MANFMT) $$f | cat -v | sed -e 's/.\^H//g' \
>$$base.0 ; \
done
@ -324,20 +327,27 @@ install-sysconf:
host-key: ssh-keygen$(EXEEXT)
@if [ -z "$(DESTDIR)" ] ; then \
if [ -f "$(DESTDIR)$(sysconfdir)/ssh_host_key" ] ; then \
echo "$(DESTDIR)$(sysconfdir)/ssh_host_key already exists, skipping." ; \
if [ -f "$(sysconfdir)/ssh_host_key" ] ; then \
echo "$(sysconfdir)/ssh_host_key already exists, skipping." ; \
else \
./ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" ; \
./ssh-keygen -t rsa1 -f $(sysconfdir)/ssh_host_key -N "" ; \
fi ; \
if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key ] ; then \
echo "$(DESTDIR)$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \
if [ -f $(sysconfdir)/ssh_host_dsa_key ] ; then \
echo "$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \
else \
./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" ; \
./ssh-keygen -t dsa -f $(sysconfdir)/ssh_host_dsa_key -N "" ; \
fi ; \
if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key ] ; then \
echo "$(DESTDIR)$(sysconfdir)/ssh_host_rsa_key already exists, skipping." ; \
if [ -f $(sysconfdir)/ssh_host_rsa_key ] ; then \
echo "$(sysconfdir)/ssh_host_rsa_key already exists, skipping." ; \
else \
./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N "" ; \
./ssh-keygen -t rsa -f $(sysconfdir)/ssh_host_rsa_key -N "" ; \
fi ; \
if [ -z "@COMMENT_OUT_ECC@" ] ; then \
if [ -f $(sysconfdir)/ssh_host_ecdsa_key ] ; then \
echo "$(sysconfdir)/ssh_host_ecdsa_key already exists, skipping." ; \
else \
./ssh-keygen -t ecdsa -f $(sysconfdir)/ssh_host_ecdsa_key -N "" ; \
fi ; \
fi ; \
fi ;
@ -345,6 +355,7 @@ host-key-force: ssh-keygen$(EXEEXT)
./ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N ""
./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N ""
./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N ""
test -z "@COMMENT_OUT_ECC@" && ./ssh-keygen -t ecdsa -f $(DESTDIR)$(sysconfdir)/ssh_host_ecdsa_key -N ""
uninstallall: uninstall
-rm -f $(DESTDIR)$(sysconfdir)/ssh_config
@ -405,6 +416,8 @@ tests interop-tests: $(TARGETS)
TEST_SSH_PUTTYGEN="puttygen"; \
TEST_SSH_CONCH="conch"; \
TEST_SSH_IPV6="@TEST_SSH_IPV6@" ; \
TEST_SSH_ECC="@TEST_SSH_ECC@" ; \
TEST_SSH_SHA256="@TEST_SSH_SHA256@" ; \
cd $(srcdir)/regress || exit $$?; \
$(MAKE) \
.OBJDIR="$${BUILDDIR}/regress" \
@ -425,7 +438,9 @@ tests interop-tests: $(TARGETS)
TEST_SSH_PLINK="$${TEST_SSH_PLINK}" \
TEST_SSH_PUTTYGEN="$${TEST_SSH_PUTTYGEN}" \
TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \
TEST_SSH_IPV6="@TEST_SSH_IPV6@" \
TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \
TEST_SSH_ECC="$${TEST_SSH_ECC}" \
TEST_SSH_SHA256="$${TEST_SSH_SHA256}" \
EXEEXT="$(EXEEXT)" \
$@ && echo all tests passed

View File

@ -12,7 +12,9 @@ are individually implemented as extensions described below.
The protocol used by OpenSSH's ssh-agent is described in the file
PROTOCOL.agent
1. transport: Protocol 2 MAC algorithm "umac-64@openssh.com"
1. Transport protocol changes
1.1. transport: Protocol 2 MAC algorithm "umac-64@openssh.com"
This is a new transport-layer MAC method using the UMAC algorithm
(rfc4418). This method is identical to the "umac-64" method documented
@ -20,7 +22,7 @@ in:
http://www.openssh.com/txt/draft-miller-secsh-umac-01.txt
2. transport: Protocol 2 compression algorithm "zlib@openssh.com"
1.2. transport: Protocol 2 compression algorithm "zlib@openssh.com"
This transport-layer compression method uses the zlib compression
algorithm (identical to the "zlib" method in rfc4253), but delays the
@ -31,14 +33,27 @@ The method is documented in:
http://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt
3. transport: New public key algorithms "ssh-rsa-cert-v00@openssh.com" and
"ssh-dsa-cert-v00@openssh.com"
1.3. transport: New public key algorithms "ssh-rsa-cert-v00@openssh.com",
"ssh-dsa-cert-v00@openssh.com",
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
"ecdsa-sha2-nistp384-cert-v01@openssh.com" and
"ecdsa-sha2-nistp521-cert-v01@openssh.com"
OpenSSH introduces two new public key algorithms to support certificate
OpenSSH introduces new public key algorithms to support certificate
authentication for users and hostkeys. These methods are documented in
the file PROTOCOL.certkeys
4. connection: Channel write close extension "eow@openssh.com"
1.4. transport: Elliptic Curve cryptography
OpenSSH supports ECC key exchange and public key authentication as
specified in RFC5656. Only the ecdsa-sha2-nistp256, ecdsa-sha2-nistp384
and ecdsa-sha2-nistp521 curves over GF(p) are supported. Elliptic
curve points encoded using point compression are NOT accepted or
generated.
2. Connection protocol changes
2.1. connection: Channel write close extension "eow@openssh.com"
The SSH connection protocol (rfc4254) provides the SSH_MSG_CHANNEL_EOF
message to allow an endpoint to signal its peer that it will send no
@ -77,8 +92,8 @@ message is only sent to OpenSSH peers (identified by banner).
Other SSH implementations may be whitelisted to receive this message
upon request.
5. connection: disallow additional sessions extension
"no-more-sessions@openssh.com"
2.2. connection: disallow additional sessions extension
"no-more-sessions@openssh.com"
Most SSH connections will only ever request a single session, but a
attacker may abuse a running ssh client to surreptitiously open
@ -105,7 +120,7 @@ of this message, the no-more-sessions request is only sent to OpenSSH
servers (identified by banner). Other SSH implementations may be
whitelisted to receive this message upon request.
6. connection: Tunnel forward extension "tun@openssh.com"
2.3. connection: Tunnel forward extension "tun@openssh.com"
OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com"
channel type. This channel type supports forwarding of network packets
@ -166,7 +181,9 @@ The contents of the "data" field for layer 2 packets is:
The "frame" field contains an IEEE 802.3 Ethernet frame, including
header.
7. sftp: Reversal of arguments to SSH_FXP_SYMLINK
3. SFTP protocol changes
3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
When OpenSSH's sftp-server was implemented, the order of the arguments
to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately,
@ -179,7 +196,7 @@ SSH_FXP_SYMLINK as follows:
string targetpath
string linkpath
8. sftp: Server extension announcement in SSH_FXP_VERSION
3.2. sftp: Server extension announcement in SSH_FXP_VERSION
OpenSSH's sftp-server lists the extensions it supports using the
standard extension announcement mechanism in the SSH_FXP_VERSION server
@ -200,7 +217,7 @@ ever changed in an incompatible way. The server MAY advertise the same
extension with multiple versions (though this is unlikely). Clients MUST
check the version number before attempting to use the extension.
9. sftp: Extension request "posix-rename@openssh.com"
3.3. sftp: Extension request "posix-rename@openssh.com"
This operation provides a rename operation with POSIX semantics, which
are different to those provided by the standard SSH_FXP_RENAME in
@ -217,7 +234,7 @@ rename(oldpath, newpath) and will respond with a SSH_FXP_STATUS message.
This extension is advertised in the SSH_FXP_VERSION hello with version
"1".
10. sftp: Extension requests "statvfs@openssh.com" and
3.4. sftp: Extension requests "statvfs@openssh.com" and
"fstatvfs@openssh.com"
These requests correspond to the statvfs and fstatvfs POSIX system
@ -258,4 +275,20 @@ The values of the f_flag bitmask are as follows:
Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are
advertised in the SSH_FXP_VERSION hello with version "2".
$OpenBSD: PROTOCOL,v 1.15 2010/02/26 20:29:54 djm Exp $
10. sftp: Extension request "hardlink@openssh.com"
This request is for creating a hard link to a regular file. This
request is implemented as a SSH_FXP_EXTENDED request with the
following format:
uint32 id
string "hardlink@openssh.com"
string oldpath
string newpath
On receiving this request the server will perform the operation
link(oldpath, newpath) and will respond with a SSH_FXP_STATUS message.
This extension is advertised in the SSH_FXP_VERSION hello with version
"1".
$OpenBSD: PROTOCOL,v 1.17 2010/12/04 00:18:01 djm Exp $

View File

@ -159,8 +159,8 @@ successfully added or a SSH_AGENT_FAILURE if an error occurred.
2.2.3 Add protocol 2 key
The OpenSSH agent supports DSA and RSA keys for protocol 2. DSA keys may
be added using the following request
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
@ -182,6 +182,30 @@ DSA certificates may be added with:
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
RSA keys may be added with this request:
byte SSH2_AGENTC_ADD_IDENTITY or
@ -214,7 +238,7 @@ 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 both DSA and RSA key add requests, "key_constraints" may only be
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
@ -294,8 +318,7 @@ Protocol 2 keys may be removed with the following request:
string key_blob
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
Algorithms" for either of the supported key types: "ssh-dss" or
"ssh-rsa".
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
@ -364,8 +387,7 @@ Followed by zero or more consecutive keys, encoded as:
string key_comment
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
Algorithms" for either of the supported key types: "ssh-dss" or
"ssh-rsa".
Algorithms" for any of the supported protocol 2 key types.
2.6 Private key operations
@ -429,9 +451,9 @@ a protocol 2 key:
uint32 flags
Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
Algorithms" for either of the supported key types: "ssh-dss" or
"ssh-rsa". "flags" is a bit-mask, but at present only one possible value
is defined (see below for its meaning):
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
@ -535,4 +557,4 @@ Locking and unlocking affects both protocol 1 and protocol 2 keys.
SSH_AGENT_CONSTRAIN_LIFETIME 1
SSH_AGENT_CONSTRAIN_CONFIRM 2
$OpenBSD: PROTOCOL.agent,v 1.5 2010/02/26 20:29:54 djm Exp $
$OpenBSD: PROTOCOL.agent,v 1.6 2010/08/31 11:54:45 djm Exp $

View File

@ -5,31 +5,37 @@ Background
----------
The SSH protocol currently supports a simple public key authentication
mechanism. Unlike other public key implementations, SSH eschews the
use of X.509 certificates and uses raw keys. This approach has some
benefits relating to simplicity of configuration and minimisation
of attack surface, but it does not support the important use-cases
of centrally managed, passwordless authentication and centrally
certified host keys.
mechanism. Unlike other public key implementations, SSH eschews the use
of X.509 certificates and uses raw keys. This approach has some benefits
relating to simplicity of configuration and minimisation of attack
surface, but it does not support the important use-cases of centrally
managed, passwordless authentication and centrally certified host keys.
These protocol extensions build on the simple public key authentication
system already in SSH to allow certificate-based authentication.
The certificates used are not traditional X.509 certificates, with
numerous options and complex encoding rules, but something rather
more minimal: a key, some identity information and usage options
that have been signed with some other trusted key.
system already in SSH to allow certificate-based authentication. The
certificates used are not traditional X.509 certificates, with numerous
options and complex encoding rules, but something rather more minimal: a
key, some identity information and usage options that have been signed
with some other trusted key.
A sshd server may be configured to allow authentication via certified
keys, by extending the existing ~/.ssh/authorized_keys mechanism
to allow specification of certification authority keys in addition
to raw user keys. The ssh client will support automatic verification
of acceptance of certified host keys, by adding a similar ability
to specify CA keys in ~/.ssh/known_hosts.
keys, by extending the existing ~/.ssh/authorized_keys mechanism to
allow specification of certification authority keys in addition to
raw user keys. The ssh client will support automatic verification of
acceptance of certified host keys, by adding a similar ability to
specify CA keys in ~/.ssh/known_hosts.
Certified keys are represented using two new key types:
ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com that
include certification information along with the public key that is used
to sign challenges. ssh-keygen performs the CA signing operation.
Certified keys are represented using new key types:
ssh-rsa-cert-v01@openssh.com
ssh-dss-cert-v01@openssh.com
ecdsa-sha2-nistp256-cert-v01@openssh.com
ecdsa-sha2-nistp384-cert-v01@openssh.com
ecdsa-sha2-nistp521-cert-v01@openssh.com
These include certification information along with the public key
that is used to sign challenges. ssh-keygen performs the CA signing
operation.
Protocol extensions
-------------------
@ -47,10 +53,9 @@ in RFC4252 section 7.
New public key formats
----------------------
The ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com key
types take a similar high-level format (note: data types and
encoding are as per RFC4251 section 5). The serialised wire encoding of
these certificates is also used for storing them on disk.
The certificate key types take a similar high-level format (note: data
types and encoding are as per RFC4251 section 5). The serialised wire
encoding of these certificates is also used for storing them on disk.
#define SSH_CERT_TYPE_USER 1
#define SSH_CERT_TYPE_HOST 2
@ -93,6 +98,26 @@ DSA certificate
string signature key
string signature
ECDSA certificate
string "ecdsa-sha2-nistp256@openssh.com" |
"ecdsa-sha2-nistp384@openssh.com" |
"ecdsa-sha2-nistp521@openssh.com"
string nonce
string curve
string public_key
uint64 serial
uint32 type
string key id
string valid principals
uint64 valid after
uint64 valid before
string critical options
string extensions
string reserved
string signature key
string signature
The nonce field is a CA-provided random bitstring of arbitrary length
(but typically 16 or 32 bytes) included to make attacks that depend on
inducing collisions in the signature hash infeasible.
@ -101,6 +126,9 @@ e and n are the RSA exponent and public modulus respectively.
p, q, g, y are the DSA parameters as described in FIPS-186-2.
curve and public key are respectively the ECDSA "[identifier]" and "Q"
defined in section 3.1 of RFC5656.
serial is an optional certificate serial number set by the CA to
provide an abbreviated way to refer to certificates from that CA.
If a CA does not wish to number its certificates it must set this
@ -123,7 +151,8 @@ any principal of the specified type. XXX DNS wildcards?
"valid after" and "valid before" specify a validity period for the
certificate. Each represents a time in seconds since 1970-01-01
00:00:00. A certificate is considered valid if:
valid after <= current time < valid before
valid after <= current time < valid before
criticial options is a set of zero or more key options encoded as
below. All such options are "critical" in the sense that an implementation
@ -137,15 +166,17 @@ 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 and ssh-dss. "Chained"
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 CA key and vice-versa.
be signed by a DSS 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
encoded according to the rules defined for the CA's public key algorithm
(RFC4253 section 6.6 for ssh-rsa and ssh-dss).
(RFC4253 section 6.6 for ssh-rsa and ssh-dss, RFC5656 for the ECDSA
types).
Critical options
----------------
@ -222,4 +253,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.7 2010/08/04 05:40:39 djm Exp $
$OpenBSD: PROTOCOL.certkeys,v 1.8 2010/08/31 11:54:45 djm Exp $

View File

@ -28,7 +28,7 @@ defined.
To open a new multiplexed session, a client may send the following
request:
uint32 MUX_C_MSG_NEW_SESSION
uint32 MUX_C_NEW_SESSION
uint32 request id
string reserved
bool want tty flag
@ -99,7 +99,7 @@ The server will reply with one of MUX_S_OK or MUX_S_PERMISSION_DENIED.
A client may request the master to establish a port forward:
uint32 MUX_C_OPEN_FORWARD
uint32 MUX_C_OPEN_FWD
uint32 request id
uint32 forwarding type
string listen host
@ -118,24 +118,23 @@ For dynamically allocated listen port the server replies with
uint32 client request id
uint32 allocated remote listen port
5. Requesting closure of port forwards
6. Requesting closure of port forwards
Note: currently unimplemented (server will always reply with MUX_S_FAILURE).
A client may request the master to establish a port forward:
uint32 MUX_C_OPEN_FORWARD
uint32 MUX_C_CLOSE_FWD
uint32 request id
uint32 forwarding type
string listen host
string listen port
string connect host
string connect port
forwarding type may be MUX_FWD_LOCAL, MUX_FWD_REMOTE, MUX_FWD_DYNAMIC.
A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a
MUX_S_FAILURE.
6. Requesting stdio forwarding
7. Requesting stdio forwarding
A client may request the master to establish a stdio forwarding:
@ -153,7 +152,7 @@ The contents of "reserved" are currently ignored.
A server may reply with a MUX_S_SESSION_OPEED, a MUX_S_PERMISSION_DENIED
or a MUX_S_FAILURE.
7. Status messages
8. Status messages
The MUX_S_OK message is empty:
@ -170,14 +169,15 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason:
uint32 client request id
string reason
7. Protocol numbers
9. Protocol numbers
#define MUX_MSG_HELLO 0x00000001
#define MUX_C_NEW_SESSION 0x10000002
#define MUX_C_ALIVE_CHECK 0x10000004
#define MUX_C_TERMINATE 0x10000005
#define MUX_C_OPEN_FORWARD 0x10000006
#define MUX_C_CLOSE_FORWARD 0x10000007
#define MUX_C_OPEN_FWD 0x10000006
#define MUX_C_CLOSE_FWD 0x10000007
#define MUX_C_NEW_STDIO_FWD 0x10000008
#define MUX_S_OK 0x80000001
#define MUX_S_PERMISSION_DENIED 0x80000002
#define MUX_S_FAILURE 0x80000003
@ -200,4 +200,4 @@ XXX server->client error/warning notifications
XXX port0 rfwd (need custom response message)
XXX send signals via mux
$OpenBSD: PROTOCOL.mux,v 1.2 2010/05/16 12:55:51 markus Exp $
$OpenBSD: PROTOCOL.mux,v 1.3 2011/01/13 21:55:25 djm Exp $

4
README
View File

@ -1,4 +1,4 @@
See http://www.openssh.com/txt/release-5.6 for the release notes.
See http://www.openssh.com/txt/release-5.7 for the release notes.
- A Japanese translation of this document and of the OpenSSH FAQ is
- available at http://www.unixuser.org/~haruyama/security/openssh/index.html
@ -62,4 +62,4 @@ References -
[6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9
[7] http://www.openssh.com/faq.html
$Id: README,v 1.74 2010/08/08 16:32:06 djm Exp $
$Id: README,v 1.75 2011/01/22 09:23:12 djm Exp $

View File

@ -1,4 +1,4 @@
/* $OpenBSD: atomicio.c,v 1.25 2007/06/25 12:02:27 dtucker Exp $ */
/* $OpenBSD: atomicio.c,v 1.26 2010/09/22 22:58:51 djm Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
@ -48,7 +48,8 @@
* ensure all of data on socket comes through. f==read || f==vwrite
*/
size_t
atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
int (*cb)(void *, size_t), void *cb_arg)
{
char *s = _s;
size_t pos = 0;
@ -73,17 +74,28 @@ atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
return pos;
default:
pos += (size_t)res;
if (cb != NULL && cb(cb_arg, (size_t)res) == -1) {
errno = EINTR;
return pos;
}
}
}
return (pos);
return pos;
}
size_t
atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
{
return atomicio6(f, fd, _s, n, NULL, NULL);
}
/*
* ensure all of data on socket comes through. f==readv || f==writev
*/
size_t
atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt)
atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt,
int (*cb)(void *, size_t), void *cb_arg)
{
size_t pos = 0, rem;
ssize_t res;
@ -137,6 +149,17 @@ atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
iov[0].iov_base = ((char *)iov[0].iov_base) + rem;
iov[0].iov_len -= rem;
}
if (cb != NULL && cb(cb_arg, (size_t)res) == -1) {
errno = EINTR;
return pos;
}
}
return pos;
}
size_t
atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt)
{
return atomiciov6(f, fd, _iov, iovcnt, NULL, NULL);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: atomicio.h,v 1.10 2006/08/03 03:34:41 deraadt Exp $ */
/* $OpenBSD: atomicio.h,v 1.11 2010/09/22 22:58:51 djm Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
@ -32,6 +32,9 @@
/*
* Ensure all of data on socket comes through. f==read || f==vwrite
*/
size_t
atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
int (*cb)(void *, size_t), void *);
size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
#define vwrite (ssize_t (*)(int, void *, size_t))write
@ -39,6 +42,9 @@ size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
/*
* ensure all of data on socket comes through. f==readv || f==writev
*/
size_t
atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt, int (*cb)(void *, size_t), void *);
size_t atomiciov(ssize_t (*)(int, const struct iovec *, int),
int, const struct iovec *, int);

View File

@ -1,4 +1,4 @@
/* $Id: audit-bsm.c,v 1.6 2008/02/25 10:05:04 dtucker Exp $ */
/* $Id: audit-bsm.c,v 1.7 2011/01/17 10:15:29 dtucker Exp $ */
/*
* TODO
@ -305,13 +305,13 @@ audit_run_command(const char *command)
}
void
audit_session_open(const char *ttyn)
audit_session_open(struct logininfo *li)
{
/* not implemented */
}
void
audit_session_close(const char *ttyn)
audit_session_close(struct logininfo *li)
{
/* not implemented */
}

126
audit-linux.c Normal file
View File

@ -0,0 +1,126 @@
/* $Id$ */
/*
* Copyright 2010 Red Hat, Inc. All rights reserved.
* Use is subject to license terms.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Red Hat author: Jan F. Chadima <jchadima@redhat.com>
*/
#include "includes.h"
#if defined(USE_LINUX_AUDIT)
#include <libaudit.h>
#include <unistd.h>
#include <string.h>
#include "log.h"
#include "audit.h"
#include "canohost.h"
const char* audit_username(void);
int
linux_audit_record_event(int uid, const char *username,
const char *hostname, const char *ip, const char *ttyn, int success)
{
int audit_fd, rc, saved_errno;
audit_fd = audit_open();
if (audit_fd < 0) {
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
errno == EAFNOSUPPORT)
return 1; /* No audit support in kernel */
else
return 0; /* Must prevent login */
}
rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN,
NULL, "login", username ? username : "(unknown)",
username == NULL ? uid : -1, hostname, ip, ttyn, success);
saved_errno = errno;
close(audit_fd);
/*
* Do not report error if the error is EPERM and sshd is run as non
* root user.
*/
if ((rc == -EPERM) && (geteuid() != 0))
rc = 0;
errno = saved_errno;
return (rc >= 0);
}
/* Below is the sshd audit API code */
void
audit_connection_from(const char *host, int port)
{
}
/* not implemented */
void
audit_run_command(const char *command)
{
/* not implemented */
}
void
audit_session_open(struct logininfo *li)
{
if (linux_audit_record_event(li->uid, NULL, li->hostname,
NULL, li->line, 1) == 0)
fatal("linux_audit_write_entry failed: %s", strerror(errno));
}
void
audit_session_close(struct logininfo *li)
{
/* not implemented */
}
void
audit_event(ssh_audit_event_t event)
{
switch(event) {
case SSH_AUTH_SUCCESS:
case SSH_CONNECTION_CLOSE:
case SSH_NOLOGIN:
case SSH_LOGIN_EXCEED_MAXTRIES:
case SSH_LOGIN_ROOT_DENIED:
break;
case SSH_AUTH_FAIL_NONE:
case SSH_AUTH_FAIL_PASSWD:
case SSH_AUTH_FAIL_KBDINT:
case SSH_AUTH_FAIL_PUBKEY:
case SSH_AUTH_FAIL_HOSTBASED:
case SSH_AUTH_FAIL_GSSAPI:
case SSH_INVALID_USER:
linux_audit_record_event(-1, audit_username(), NULL,
get_remote_ipaddr(), "sshd", 0);
break;
default:
debug("%s: unhandled event %d", __func__, event);
}
}
#endif /* USE_LINUX_AUDIT */

10
audit.c
View File

@ -1,4 +1,4 @@
/* $Id: audit.c,v 1.5 2006/09/01 05:38:36 djm Exp $ */
/* $Id: audit.c,v 1.6 2011/01/17 10:15:30 dtucker Exp $ */
/*
* Copyright (c) 2004, 2005 Darren Tucker. All rights reserved.
@ -147,9 +147,9 @@ audit_event(ssh_audit_event_t event)
* within a single connection.
*/
void
audit_session_open(const char *ttyn)
audit_session_open(struct logininfo *li)
{
const char *t = ttyn ? ttyn : "(no tty)";
const char *t = li->line ? li->line : "(no tty)";
debug("audit session open euid %d user %s tty name %s", geteuid(),
audit_username(), t);
@ -163,9 +163,9 @@ audit_session_open(const char *ttyn)
* within a single connection.
*/
void
audit_session_close(const char *ttyn)
audit_session_close(struct logininfo *li)
{
const char *t = ttyn ? ttyn : "(no tty)";
const char *t = li->line ? li->line : "(no tty)";
debug("audit session close euid %d user %s tty name %s", geteuid(),
audit_username(), t);

View File

@ -1,4 +1,4 @@
/* $Id: audit.h,v 1.3 2006/08/05 14:05:10 dtucker Exp $ */
/* $Id: audit.h,v 1.4 2011/01/17 10:15:30 dtucker Exp $ */
/*
* Copyright (c) 2004, 2005 Darren Tucker. All rights reserved.
@ -26,6 +26,9 @@
#ifndef _SSH_AUDIT_H
# define _SSH_AUDIT_H
#include "loginrec.h"
enum ssh_audit_event_type {
SSH_LOGIN_EXCEED_MAXTRIES,
SSH_LOGIN_ROOT_DENIED,
@ -46,8 +49,8 @@ typedef enum ssh_audit_event_type ssh_audit_event_t;
void audit_connection_from(const char *, int);
void audit_event(ssh_audit_event_t);
void audit_session_open(const char *);
void audit_session_close(const char *);
void audit_session_open(struct logininfo *);
void audit_session_close(struct logininfo *);
void audit_run_command(const char *);
ssh_audit_event_t audit_classify_auth(const char *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-options.c,v 1.52 2010/05/20 23:46:02 djm Exp $ */
/* $OpenBSD: auth-options.c,v 1.54 2010/12/24 21:41:48 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -172,7 +172,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
goto bad_option;
}
forced_command[i] = '\0';
auth_debug_add("Forced command: %.900s", forced_command);
auth_debug_add("Forced command.");
opts++;
goto next_option;
}
@ -444,7 +444,7 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
buffer_append(&c, optblob, optblob_len);
while (buffer_len(&c) > 0) {
if ((name = buffer_get_string_ret(&c, &nlen)) == NULL ||
if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL ||
(data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) {
error("Certificate options corrupt");
goto out;
@ -479,7 +479,7 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
}
if (!found && (which & OPTIONS_CRITICAL) != 0) {
if (strcmp(name, "force-command") == 0) {
if ((command = buffer_get_string_ret(&data,
if ((command = buffer_get_cstring_ret(&data,
&clen)) == NULL) {
error("Certificate constraint \"%s\" "
"corrupt", name);
@ -500,7 +500,7 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
found = 1;
}
if (strcmp(name, "source-address") == 0) {
if ((allowed = buffer_get_string_ret(&data,
if ((allowed = buffer_get_cstring_ret(&data,
&clen)) == NULL) {
error("Certificate constraint "
"\"%s\" corrupt", name);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-rsa.c,v 1.78 2010/07/13 23:13:16 djm Exp $ */
/* $OpenBSD: auth-rsa.c,v 1.79 2010/12/03 23:55:27 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -94,9 +94,6 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
MD5_CTX md;
int len;
if (auth_key_is_revoked(key))
return 0;
/* don't allow short keys */
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
@ -249,6 +246,10 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
"actual %d vs. announced %d.",
file, linenum, BN_num_bits(key->rsa->n), bits);
/* Never accept a revoked key */
if (auth_key_is_revoked(key))
break;
/* We have found the desired key. */
/*
* If our options do not allow this key to be used,

32
auth.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.89 2010/08/04 05:42:47 djm Exp $ */
/* $OpenBSD: auth.c,v 1.91 2010/11/29 23:45:51 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -379,16 +379,15 @@ HostStatus
check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
const char *sysfile, const char *userfile)
{
Key *found;
char *user_hostfile;
struct stat st;
HostStatus host_status;
struct hostkeys *hostkeys;
const struct hostkey_entry *found;
/* Check if we know the host and its host key. */
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
host_status = check_host_in_hostfile(sysfile, host, key, found, NULL);
if (host_status != HOST_OK && userfile != NULL) {
hostkeys = init_hostkeys();
load_hostkeys(hostkeys, host, sysfile);
if (userfile != NULL) {
user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
if (options.strict_modes &&
(stat(user_hostfile, &st) == 0) &&
@ -401,16 +400,23 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
user_hostfile);
} else {
temporarily_use_uid(pw);
host_status = check_host_in_hostfile(user_hostfile,
host, key, found, NULL);
load_hostkeys(hostkeys, host, user_hostfile);
restore_uid();
}
xfree(user_hostfile);
}
key_free(found);
host_status = check_key_in_hostkeys(hostkeys, key, &found);
if (host_status == HOST_REVOKED)
error("WARNING: revoked key for %s attempted authentication",
found->host);
else if (host_status == HOST_OK)
debug("%s: key for %s found at %s:%ld", __func__,
found->host, found->file, found->line);
else
debug("%s: key for host %s not found", __func__, host);
free_hostkeys(hostkeys);
debug2("check_key_in_hostfiles: key %s for %s", host_status == HOST_OK ?
"ok" : "not found", host);
return host_status;
}
@ -518,7 +524,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
close(fd);
return NULL;
}
if (options.strict_modes &&
if (strict_modes &&
secure_filename(f, file, pw, line, sizeof(line)) != 0) {
fclose(f);
logit("Authentication refused: %s", line);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth1.c,v 1.74 2010/06/25 08:46:17 djm Exp $ */
/* $OpenBSD: auth1.c,v 1.75 2010/08/31 09:58:37 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -167,7 +167,7 @@ auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen)
* trust the client; root on the client machine can
* claim to be any user.
*/
client_user = packet_get_string(&ulen);
client_user = packet_get_cstring(&ulen);
/* Get the client host key. */
client_host_key = key_new(KEY_RSA1);
@ -389,7 +389,7 @@ do_authentication(Authctxt *authctxt)
packet_read_expect(SSH_CMSG_USER);
/* Get the user name. */
user = packet_get_string(&ulen);
user = packet_get_cstring(&ulen);
packet_check_eom();
if ((style = strchr(user, ':')) != NULL)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-jpake.c,v 1.3 2009/03/05 07:18:19 djm Exp $ */
/* $OpenBSD: auth2-jpake.c,v 1.4 2010/08/31 11:54:45 djm Exp $ */
/*
* Copyright (c) 2008 Damien Miller. All rights reserved.
*
@ -162,6 +162,11 @@ derive_rawsalt(const char *username, u_char *rawsalt, u_int len)
fatal("%s: DSA key missing priv_key", __func__);
buffer_put_bignum2(&b, k->dsa->priv_key);
break;
case KEY_ECDSA:
if (EC_KEY_get0_private_key(k->ecdsa) == NULL)
fatal("%s: ECDSA key missing priv_key", __func__);
buffer_put_bignum2(&b, EC_KEY_get0_private_key(k->ecdsa));
break;
default:
fatal("%s: unknown key type %d", __func__, k->type);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-pubkey.c,v 1.26 2010/06/29 23:16:46 djm Exp $ */
/* $OpenBSD: auth2-pubkey.c,v 1.27 2010/11/20 05:12:38 deraadt Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -232,7 +232,7 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert)
if ((ep = strrchr(cp, ' ')) != NULL ||
(ep = strrchr(cp, '\t')) != NULL) {
for (; *ep == ' ' || *ep == '\t'; ep++)
;;
;
line_opts = cp;
cp = ep;
}

10
auth2.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2.c,v 1.121 2009/06/22 05:39:28 dtucker Exp $ */
/* $OpenBSD: auth2.c,v 1.122 2010/08/31 09:58:37 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -182,7 +182,7 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
Authctxt *authctxt = ctxt;
u_int len;
int acceptit = 0;
char *service = packet_get_string(&len);
char *service = packet_get_cstring(&len);
packet_check_eom();
if (authctxt == NULL)
@ -221,9 +221,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
if (authctxt == NULL)
fatal("input_userauth_request: no authctxt");
user = packet_get_string(NULL);
service = packet_get_string(NULL);
method = packet_get_string(NULL);
user = packet_get_cstring(NULL);
service = packet_get_cstring(NULL);
method = packet_get_cstring(NULL);
debug("userauth-request for user %s service %s method %s", user, service, method);
debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfd.c,v 1.83 2010/04/16 01:47:26 djm Exp $ */
/* $OpenBSD: authfd.c,v 1.84 2010/08/31 11:54:45 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -509,6 +509,21 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
buffer_len(&key->cert->certblob));
buffer_put_bignum2(b, key->dsa->priv_key);
break;
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
buffer_put_cstring(b, key_curve_nid_to_name(key->ecdsa_nid));
buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa),
EC_KEY_get0_public_key(key->ecdsa));
buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));
break;
case KEY_ECDSA_CERT:
if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
fatal("%s: no cert/certblob", __func__);
buffer_put_string(b, buffer_ptr(&key->cert->certblob),
buffer_len(&key->cert->certblob));
buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));
break;
#endif
}
buffer_put_cstring(b, comment);
}
@ -541,6 +556,8 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
case KEY_DSA:
case KEY_DSA_CERT:
case KEY_DSA_CERT_V00:
case KEY_ECDSA:
case KEY_ECDSA_CERT:
type = constrained ?
SSH2_AGENTC_ADD_ID_CONSTRAINED :
SSH2_AGENTC_ADD_IDENTITY;
@ -589,7 +606,8 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key)
buffer_put_bignum(&msg, key->rsa->e);
buffer_put_bignum(&msg, key->rsa->n);
} else if (key_type_plain(key->type) == KEY_DSA ||
key_type_plain(key->type) == KEY_RSA) {
key_type_plain(key->type) == KEY_RSA ||
key_type_plain(key->type) == KEY_ECDSA) {
key_to_blob(key, &blob, &blen);
buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
buffer_put_string(&msg, blob, blen);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfile.c,v 1.82 2010/08/04 05:49:22 djm Exp $ */
/* $OpenBSD: authfile.c,v 1.87 2010/11/29 18:57:04 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -74,19 +74,18 @@ static const char authfile_id_string[] =
"SSH PRIVATE KEY FILE FORMAT 1.1\n";
/*
* Saves the authentication (private) key in a file, encrypting it with
* passphrase. The identification of the file (lowest 64 bits of n) will
* Serialises the authentication (private) key to a blob, encrypting it with
* passphrase. The identification of the blob (lowest 64 bits of n) will
* precede the key to provide identification of the key without needing a
* passphrase.
*/
static int
key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
const char *comment)
{
Buffer buffer, encrypted;
u_char buf[100], *cp;
int fd, i, cipher_num;
int i, cipher_num;
CipherContext ciphercontext;
Cipher *cipher;
u_int32_t rnd;
@ -157,88 +156,200 @@ key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
memset(buf, 0, sizeof(buf));
buffer_free(&buffer);
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) {
error("open %s failed: %s.", filename, strerror(errno));
buffer_free(&encrypted);
return 0;
}
if (atomicio(vwrite, fd, buffer_ptr(&encrypted),
buffer_len(&encrypted)) != buffer_len(&encrypted)) {
error("write to key file %s failed: %s", filename,
strerror(errno));
buffer_free(&encrypted);
close(fd);
unlink(filename);
return 0;
}
close(fd);
buffer_append(blob, buffer_ptr(&encrypted), buffer_len(&encrypted));
buffer_free(&encrypted);
return 1;
}
/* save SSH v2 key in OpenSSL PEM format */
/* convert SSH v2 key in OpenSSL PEM format */
static int
key_save_private_pem(Key *key, const char *filename, const char *_passphrase,
key_private_pem_to_blob(Key *key, Buffer *blob, const char *_passphrase,
const char *comment)
{
FILE *fp;
int fd;
int success = 0;
int len = strlen(_passphrase);
int blen, len = strlen(_passphrase);
u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
#else
const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
#endif
const u_char *bptr;
BIO *bio;
if (len > 0 && len <= 4) {
error("passphrase too short: have %d bytes, need > 4", len);
return 0;
}
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) {
error("open %s failed: %s.", filename, strerror(errno));
return 0;
}
fp = fdopen(fd, "w");
if (fp == NULL) {
error("fdopen %s failed: %s.", filename, strerror(errno));
close(fd);
if ((bio = BIO_new(BIO_s_mem())) == NULL) {
error("%s: BIO_new failed", __func__);
return 0;
}
switch (key->type) {
case KEY_DSA:
success = PEM_write_DSAPrivateKey(fp, key->dsa,
success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
cipher, passphrase, len, NULL, NULL);
break;
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
cipher, passphrase, len, NULL, NULL);
break;
#endif
case KEY_RSA:
success = PEM_write_RSAPrivateKey(fp, key->rsa,
success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
cipher, passphrase, len, NULL, NULL);
break;
}
fclose(fp);
if (success) {
if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0)
success = 0;
else
buffer_append(blob, bptr, blen);
}
BIO_free(bio);
return success;
}
/* Save a key blob to a file */
static int
key_save_private_blob(Buffer *keybuf, const char *filename)
{
int fd;
if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
error("open %s failed: %s.", filename, strerror(errno));
return 0;
}
if (atomicio(vwrite, fd, buffer_ptr(keybuf),
buffer_len(keybuf)) != buffer_len(keybuf)) {
error("write to key file %s failed: %s", filename,
strerror(errno));
close(fd);
unlink(filename);
return 0;
}
close(fd);
return 1;
}
/* Serialise "key" to buffer "blob" */
static int
key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
const char *comment)
{
switch (key->type) {
case KEY_RSA1:
return key_private_rsa1_to_blob(key, blob, passphrase, comment);
case KEY_DSA:
case KEY_ECDSA:
case KEY_RSA:
return key_private_pem_to_blob(key, blob, passphrase, comment);
default:
error("%s: cannot save key type %d", __func__, key->type);
return 0;
}
}
int
key_save_private(Key *key, const char *filename, const char *passphrase,
const char *comment)
{
switch (key->type) {
case KEY_RSA1:
return key_save_private_rsa1(key, filename, passphrase,
comment);
case KEY_DSA:
case KEY_RSA:
return key_save_private_pem(key, filename, passphrase,
comment);
default:
break;
Buffer keyblob;
int success = 0;
buffer_init(&keyblob);
if (!key_private_to_blob(key, &keyblob, passphrase, comment))
goto out;
if (!key_save_private_blob(&keyblob, filename))
goto out;
success = 1;
out:
buffer_free(&keyblob);
return success;
}
/*
* Parse the public, unencrypted portion of a RSA1 key.
*/
static Key *
key_parse_public_rsa1(Buffer *blob, char **commentp)
{
Key *pub;
/* Check that it is at least big enough to contain the ID string. */
if (buffer_len(blob) < sizeof(authfile_id_string)) {
debug3("Truncated RSA1 identifier");
return NULL;
}
error("key_save_private: cannot save key type %d", key->type);
return 0;
/*
* Make sure it begins with the id string. Consume the id string
* from the buffer.
*/
if (memcmp(buffer_ptr(blob), authfile_id_string,
sizeof(authfile_id_string)) != 0) {
debug3("Incorrect RSA1 identifier");
return NULL;
}
buffer_consume(blob, sizeof(authfile_id_string));
/* Skip cipher type and reserved data. */
(void) buffer_get_char(blob); /* cipher type */
(void) buffer_get_int(blob); /* reserved */
/* Read the public key from the buffer. */
(void) buffer_get_int(blob);
pub = key_new(KEY_RSA1);
buffer_get_bignum(blob, pub->rsa->n);
buffer_get_bignum(blob, pub->rsa->e);
if (commentp)
*commentp = buffer_get_string(blob, NULL);
/* The encrypted private part is not parsed by this function. */
buffer_clear(blob);
return pub;
}
/* Load the contents of a key file into a buffer */
static int
key_load_file(int fd, const char *filename, Buffer *blob)
{
size_t len;
u_char *cp;
struct stat st;
if (fstat(fd, &st) < 0) {
error("%s: fstat of key file %.200s%sfailed: %.100s", __func__,
filename == NULL ? "" : filename,
filename == NULL ? "" : " ",
strerror(errno));
close(fd);
return 0;
}
if (st.st_size > 1*1024*1024) {
error("%s: key file %.200s%stoo large", __func__,
filename == NULL ? "" : filename,
filename == NULL ? "" : " ");
close(fd);
return 0;
}
len = (size_t)st.st_size; /* truncated */
buffer_init(blob);
cp = buffer_append_space(blob, len);
if (atomicio(read, fd, cp, len) != len) {
debug("%s: read from key file %.200s%sfailed: %.100s", __func__,
filename == NULL ? "" : filename,
filename == NULL ? "" : " ",
strerror(errno));
buffer_clear(blob);
close(fd);
return 0;
}
return 1;
}
/*
@ -246,67 +357,21 @@ key_save_private(Key *key, const char *filename, const char *passphrase,
* encountered (the file does not exist or is not readable), and the key
* otherwise.
*/
static Key *
key_load_public_rsa1(int fd, const char *filename, char **commentp)
{
Buffer buffer;
Key *pub;
struct stat st;
char *cp;
u_int i;
size_t len;
if (fstat(fd, &st) < 0) {
error("fstat for key file %.200s failed: %.100s",
filename, strerror(errno));
return NULL;
}
if (st.st_size > 1*1024*1024) {
error("key file %.200s too large", filename);
return NULL;
}
len = (size_t)st.st_size; /* truncated */
buffer_init(&buffer);
cp = buffer_append_space(&buffer, len);
if (atomicio(read, fd, cp, len) != len) {
debug("Read from key file %.200s failed: %.100s", filename,
strerror(errno));
if (!key_load_file(fd, filename, &buffer)) {
buffer_free(&buffer);
return NULL;
}
/* Check that it is at least big enough to contain the ID string. */
if (len < sizeof(authfile_id_string)) {
debug3("Not a RSA1 key file %.200s.", filename);
buffer_free(&buffer);
return NULL;
}
/*
* Make sure it begins with the id string. Consume the id string
* from the buffer.
*/
for (i = 0; i < sizeof(authfile_id_string); i++)
if (buffer_get_char(&buffer) != authfile_id_string[i]) {
debug3("Not a RSA1 key file %.200s.", filename);
buffer_free(&buffer);
return NULL;
}
/* Skip cipher type and reserved data. */
(void) buffer_get_char(&buffer); /* cipher type */
(void) buffer_get_int(&buffer); /* reserved */
/* Read the public key from the buffer. */
(void) buffer_get_int(&buffer);
pub = key_new(KEY_RSA1);
buffer_get_bignum(&buffer, pub->rsa->n);
buffer_get_bignum(&buffer, pub->rsa->e);
if (commentp)
*commentp = buffer_get_string(&buffer, NULL);
/* The encrypted private part is not parsed by this function. */
pub = key_parse_public_rsa1(&buffer, commentp);
if (pub == NULL)
debug3("Could not load \"%s\" as a RSA1 public key", filename);
buffer_free(&buffer);
return pub;
}
@ -329,113 +394,73 @@ key_load_public_type(int type, const char *filename, char **commentp)
return NULL;
}
/*
* Loads the private key from the file. Returns 0 if an error is encountered
* (file does not exist or is not readable, or passphrase is bad). This
* initializes the private key.
* Assumes we are called under uid of the owner of the file.
*/
static Key *
key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
char **commentp)
key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
{
u_int i;
int check1, check2, cipher_type;
size_t len;
Buffer buffer, decrypted;
Buffer decrypted;
u_char *cp;
CipherContext ciphercontext;
Cipher *cipher;
Key *prv = NULL;
struct stat st;
if (fstat(fd, &st) < 0) {
error("fstat for key file %.200s failed: %.100s",
filename, strerror(errno));
close(fd);
return NULL;
}
if (st.st_size > 1*1024*1024) {
error("key file %.200s too large", filename);
close(fd);
return (NULL);
}
len = (size_t)st.st_size; /* truncated */
buffer_init(&buffer);
cp = buffer_append_space(&buffer, len);
if (atomicio(read, fd, cp, len) != len) {
debug("Read from key file %.200s failed: %.100s", filename,
strerror(errno));
buffer_free(&buffer);
close(fd);
return NULL;
}
/* Check that it is at least big enough to contain the ID string. */
if (len < sizeof(authfile_id_string)) {
debug3("Not a RSA1 key file %.200s.", filename);
buffer_free(&buffer);
close(fd);
if (buffer_len(blob) < sizeof(authfile_id_string)) {
debug3("Truncated RSA1 identifier");
return NULL;
}
/*
* Make sure it begins with the id string. Consume the id string
* from the buffer.
*/
for (i = 0; i < sizeof(authfile_id_string); i++)
if (buffer_get_char(&buffer) != authfile_id_string[i]) {
debug3("Not a RSA1 key file %.200s.", filename);
buffer_free(&buffer);
close(fd);
return NULL;
}
if (memcmp(buffer_ptr(blob), authfile_id_string,
sizeof(authfile_id_string)) != 0) {
debug3("Incorrect RSA1 identifier");
return NULL;
}
buffer_consume(blob, sizeof(authfile_id_string));
/* Read cipher type. */
cipher_type = buffer_get_char(&buffer);
(void) buffer_get_int(&buffer); /* Reserved data. */
cipher_type = buffer_get_char(blob);
(void) buffer_get_int(blob); /* Reserved data. */
/* Read the public key from the buffer. */
(void) buffer_get_int(&buffer);
(void) buffer_get_int(blob);
prv = key_new_private(KEY_RSA1);
buffer_get_bignum(&buffer, prv->rsa->n);
buffer_get_bignum(&buffer, prv->rsa->e);
buffer_get_bignum(blob, prv->rsa->n);
buffer_get_bignum(blob, prv->rsa->e);
if (commentp)
*commentp = buffer_get_string(&buffer, NULL);
*commentp = buffer_get_string(blob, NULL);
else
xfree(buffer_get_string(&buffer, NULL));
(void)buffer_get_string_ptr(blob, NULL);
/* Check that it is a supported cipher. */
cipher = cipher_by_number(cipher_type);
if (cipher == NULL) {
debug("Unsupported cipher %d used in key file %.200s.",
cipher_type, filename);
buffer_free(&buffer);
debug("Unsupported RSA1 cipher %d", cipher_type);
goto fail;
}
/* Initialize space for decrypted data. */
buffer_init(&decrypted);
cp = buffer_append_space(&decrypted, buffer_len(&buffer));
cp = buffer_append_space(&decrypted, buffer_len(blob));
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_DECRYPT);
cipher_crypt(&ciphercontext, cp,
buffer_ptr(&buffer), buffer_len(&buffer));
buffer_ptr(blob), buffer_len(blob));
cipher_cleanup(&ciphercontext);
memset(&ciphercontext, 0, sizeof(ciphercontext));
buffer_free(&buffer);
buffer_clear(blob);
check1 = buffer_get_char(&decrypted);
check2 = buffer_get_char(&decrypted);
if (check1 != buffer_get_char(&decrypted) ||
check2 != buffer_get_char(&decrypted)) {
if (strcmp(passphrase, "") != 0)
debug("Bad passphrase supplied for key file %.200s.",
filename);
debug("Bad passphrase supplied for RSA1 key");
/* Bad passphrase. */
buffer_free(&decrypted);
goto fail;
@ -454,38 +479,37 @@ key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
/* enable blinding */
if (RSA_blinding_on(prv->rsa, NULL) != 1) {
error("key_load_private_rsa1: RSA_blinding_on failed");
error("%s: RSA_blinding_on failed", __func__);
goto fail;
}
close(fd);
return prv;
fail:
if (commentp)
xfree(*commentp);
close(fd);
key_free(prv);
return NULL;
}
Key *
key_load_private_pem(int fd, int type, const char *passphrase,
static Key *
key_parse_private_pem(Buffer *blob, int type, const char *passphrase,
char **commentp)
{
FILE *fp;
EVP_PKEY *pk = NULL;
Key *prv = NULL;
char *name = "<no key>";
BIO *bio;
fp = fdopen(fd, "r");
if (fp == NULL) {
error("fdopen failed: %s", strerror(errno));
close(fd);
if ((bio = BIO_new_mem_buf(buffer_ptr(blob),
buffer_len(blob))) == NULL) {
error("%s: BIO_new_mem_buf failed", __func__);
return NULL;
}
pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);
pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase);
BIO_free(bio);
if (pk == NULL) {
debug("PEM_read_PrivateKey failed");
debug("%s: PEM_read_PrivateKey failed", __func__);
(void)ERR_get_error();
} else if (pk->type == EVP_PKEY_RSA &&
(type == KEY_UNSPEC||type==KEY_RSA)) {
@ -497,7 +521,7 @@ key_load_private_pem(int fd, int type, const char *passphrase,
RSA_print_fp(stderr, prv->rsa, 8);
#endif
if (RSA_blinding_on(prv->rsa, NULL) != 1) {
error("key_load_private_pem: RSA_blinding_on failed");
error("%s: RSA_blinding_on failed", __func__);
key_free(prv);
prv = NULL;
}
@ -510,11 +534,31 @@ key_load_private_pem(int fd, int type, const char *passphrase,
#ifdef DEBUG_PK
DSA_print_fp(stderr, prv->dsa, 8);
#endif
#ifdef OPENSSL_HAS_ECC
} else if (pk->type == EVP_PKEY_EC &&
(type == KEY_UNSPEC||type==KEY_ECDSA)) {
prv = key_new(KEY_UNSPEC);
prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
prv->type = KEY_ECDSA;
if ((prv->ecdsa_nid = key_ecdsa_key_to_nid(prv->ecdsa)) == -1 ||
key_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
key_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
key_ec_validate_private(prv->ecdsa) != 0) {
error("%s: bad ECDSA key", __func__);
key_free(prv);
prv = NULL;
}
name = "ecdsa w/o comment";
#ifdef DEBUG_PK
if (prv != NULL && prv->ecdsa != NULL)
key_dump_ec_key(prv->ecdsa);
#endif
#endif /* OPENSSL_HAS_ECC */
} else {
error("PEM_read_PrivateKey: mismatch or "
"unknown EVP_PKEY save_type %d", pk->save_type);
error("%s: PEM_read_PrivateKey: mismatch or "
"unknown EVP_PKEY save_type %d", __func__, pk->save_type);
}
fclose(fp);
if (pk != NULL)
EVP_PKEY_free(pk);
if (prv != NULL && commentp)
@ -524,6 +568,23 @@ key_load_private_pem(int fd, int type, const char *passphrase,
return prv;
}
Key *
key_load_private_pem(int fd, int type, const char *passphrase,
char **commentp)
{
Buffer buffer;
Key *prv;
buffer_init(&buffer);
if (!key_load_file(fd, NULL, &buffer)) {
buffer_free(&buffer);
return NULL;
}
prv = key_parse_private_pem(&buffer, type, passphrase, commentp);
buffer_free(&buffer);
return prv;
}
int
key_perm_ok(int fd, const char *filename)
{
@ -552,11 +613,31 @@ key_perm_ok(int fd, const char *filename)
return 1;
}
static Key *
key_parse_private_type(Buffer *blob, int type, const char *passphrase,
char **commentp)
{
switch (type) {
case KEY_RSA1:
return key_parse_private_rsa1(blob, passphrase, commentp);
case KEY_DSA:
case KEY_ECDSA:
case KEY_RSA:
case KEY_UNSPEC:
return key_parse_private_pem(blob, type, passphrase, commentp);
default:
break;
}
return NULL;
}
Key *
key_load_private_type(int type, const char *filename, const char *passphrase,
char **commentp, int *perm_ok)
{
int fd;
Key *ret;
Buffer buffer;
fd = open(filename, O_RDONLY);
if (fd < 0) {
@ -575,21 +656,17 @@ key_load_private_type(int type, const char *filename, const char *passphrase,
}
if (perm_ok != NULL)
*perm_ok = 1;
switch (type) {
case KEY_RSA1:
return key_load_private_rsa1(fd, filename, passphrase,
commentp);
/* closes fd */
case KEY_DSA:
case KEY_RSA:
case KEY_UNSPEC:
return key_load_private_pem(fd, type, passphrase, commentp);
/* closes fd */
default:
buffer_init(&buffer);
if (!key_load_file(fd, filename, &buffer)) {
buffer_free(&buffer);
close(fd);
break;
return NULL;
}
return NULL;
close(fd);
ret = key_parse_private_type(&buffer, type, passphrase, commentp);
buffer_free(&buffer);
return ret;
}
Key *
@ -597,6 +674,7 @@ key_load_private(const char *filename, const char *passphrase,
char **commentp)
{
Key *pub, *prv;
Buffer buffer, pubcopy;
int fd;
fd = open(filename, O_RDONLY);
@ -610,20 +688,33 @@ key_load_private(const char *filename, const char *passphrase,
close(fd);
return NULL;
}
pub = key_load_public_rsa1(fd, filename, commentp);
lseek(fd, (off_t) 0, SEEK_SET); /* rewind */
buffer_init(&buffer);
if (!key_load_file(fd, filename, &buffer)) {
buffer_free(&buffer);
close(fd);
return NULL;
}
close(fd);
buffer_init(&pubcopy);
buffer_append(&pubcopy, buffer_ptr(&buffer), buffer_len(&buffer));
/* it's a SSH v1 key if the public key part is readable */
pub = key_parse_public_rsa1(&pubcopy, commentp);
buffer_free(&pubcopy);
if (pub == NULL) {
/* closes fd */
prv = key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL);
prv = key_parse_private_type(&buffer, KEY_UNSPEC,
passphrase, NULL);
/* use the filename as a comment for PEM */
if (commentp && prv)
*commentp = xstrdup(filename);
} else {
/* it's a SSH v1 key if the public key part is readable */
key_free(pub);
/* closes fd */
prv = key_load_private_rsa1(fd, filename, passphrase, NULL);
/* key_parse_public_rsa1() has already loaded the comment */
prv = key_parse_private_type(&buffer, KEY_RSA1, passphrase,
NULL);
}
buffer_free(&buffer);
return prv;
}
@ -721,6 +812,7 @@ key_load_private_cert(int type, const char *filename, const char *passphrase,
switch (type) {
case KEY_RSA:
case KEY_DSA:
case KEY_ECDSA:
break;
default:
error("%s: unsupported key type", __func__);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: bufaux.c,v 1.49 2010/03/26 03:13:17 djm Exp $ */
/* $OpenBSD: bufaux.c,v 1.50 2010/08/31 09:58:37 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -202,6 +202,39 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr)
return (ret);
}
char *
buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
{
u_int length;
char *cp, *ret = buffer_get_string_ret(buffer, &length);
if (ret == NULL)
return NULL;
if ((cp = memchr(ret, '\0', length)) != NULL) {
/* XXX allow \0 at end-of-string for a while, remove later */
if (cp == ret + length - 1)
error("buffer_get_cstring_ret: string contains \\0");
else {
bzero(ret, length);
xfree(ret);
return NULL;
}
}
if (length_ptr != NULL)
*length_ptr = length;
return ret;
}
char *
buffer_get_cstring(Buffer *buffer, u_int *length_ptr)
{
char *ret;
if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL)
fatal("buffer_get_cstring: buffer error");
return ret;
}
void *
buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
{

146
bufec.c Normal file
View File

@ -0,0 +1,146 @@
/* $OpenBSD: bufec.c,v 1.1 2010/08/31 11:54:45 djm Exp $ */
/*
* Copyright (c) 2010 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifdef OPENSSL_HAS_ECC
#include <sys/types.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#include "misc.h"
/*
* Maximum supported EC GFp field length is 528 bits. SEC1 uncompressed
* encoding represents this as two bitstring points that should each
* be no longer than the field length, SEC1 specifies a 1 byte
* point type header.
* Being paranoid here may insulate us to parsing problems in
* EC_POINT_oct2point.
*/
#define BUFFER_MAX_ECPOINT_LEN ((528*2 / 8) + 1)
/*
* Append an EC_POINT to the buffer as a string containing a SEC1 encoded
* uncompressed point. Fortunately OpenSSL handles the gory details for us.
*/
int
buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
const EC_POINT *point)
{
u_char *buf = NULL;
size_t len;
BN_CTX *bnctx;
int ret = -1;
/* Determine length */
if ((bnctx = BN_CTX_new()) == NULL)
fatal("%s: BN_CTX_new failed", __func__);
len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
NULL, 0, bnctx);
if (len > BUFFER_MAX_ECPOINT_LEN) {
error("%s: giant EC point: len = %lu (max %u)",
__func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN);
goto out;
}
/* Convert */
buf = xmalloc(len);
if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
buf, len, bnctx) != len) {
error("%s: EC_POINT_point2oct length mismatch", __func__);
goto out;
}
/* Append */
buffer_put_string(buffer, buf, len);
ret = 0;
out:
if (buf != NULL) {
bzero(buf, len);
xfree(buf);
}
BN_CTX_free(bnctx);
return ret;
}
void
buffer_put_ecpoint(Buffer *buffer, const EC_GROUP *curve,
const EC_POINT *point)
{
if (buffer_put_ecpoint_ret(buffer, curve, point) == -1)
fatal("%s: buffer error", __func__);
}
int
buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
EC_POINT *point)
{
u_char *buf;
u_int len;
BN_CTX *bnctx;
int ret = -1;
if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) {
error("%s: invalid point", __func__);
return -1;
}
if ((bnctx = BN_CTX_new()) == NULL)
fatal("%s: BN_CTX_new failed", __func__);
if (len > BUFFER_MAX_ECPOINT_LEN) {
error("%s: EC_POINT too long: %u > max %u", __func__,
len, BUFFER_MAX_ECPOINT_LEN);
goto out;
}
if (len == 0) {
error("%s: EC_POINT buffer is empty", __func__);
goto out;
}
if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) {
error("%s: EC_POINT is in an incorrect form: "
"0x%02x (want 0x%02x)", __func__, buf[0],
POINT_CONVERSION_UNCOMPRESSED);
goto out;
}
if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) {
error("buffer_get_bignum2_ret: BN_bin2bn failed");
goto out;
}
/* EC_POINT_oct2point verifies that the point is on the curve for us */
ret = 0;
out:
BN_CTX_free(bnctx);
bzero(buf, len);
xfree(buf);
return ret;
}
void
buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve,
EC_POINT *point)
{
if (buffer_get_ecpoint_ret(buffer, curve, point) == -1)
fatal("%s: buffer error", __func__);
}
#endif /* OPENSSL_HAS_ECC */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: buffer.h,v 1.19 2010/02/09 03:56:28 djm Exp $ */
/* $OpenBSD: buffer.h,v 1.21 2010/08/31 11:54:45 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -68,6 +68,7 @@ void buffer_put_char(Buffer *, int);
void *buffer_get_string(Buffer *, u_int *);
void *buffer_get_string_ptr(Buffer *, u_int *);
void buffer_put_string(Buffer *, const void *, u_int);
char *buffer_get_cstring(Buffer *, u_int *);
void buffer_put_cstring(Buffer *, const char *);
#define buffer_skip_string(b) \
@ -81,7 +82,17 @@ int buffer_get_short_ret(u_short *, Buffer *);
int buffer_get_int_ret(u_int *, Buffer *);
int buffer_get_int64_ret(u_int64_t *, Buffer *);
void *buffer_get_string_ret(Buffer *, u_int *);
char *buffer_get_cstring_ret(Buffer *, u_int *);
void *buffer_get_string_ptr_ret(Buffer *, u_int *);
int buffer_get_char_ret(char *, Buffer *);
#ifdef OPENSSL_HAS_ECC
#include <openssl/ec.h>
int buffer_put_ecpoint_ret(Buffer *, const EC_GROUP *, const EC_POINT *);
void buffer_put_ecpoint(Buffer *, const EC_GROUP *, const EC_POINT *);
int buffer_get_ecpoint_ret(Buffer *, const EC_GROUP *, EC_POINT *);
void buffer_get_ecpoint(Buffer *, const EC_GROUP *, EC_POINT *);
#endif
#endif /* BUFFER_H */

View File

@ -199,7 +199,7 @@ ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr));
port = a6->sin6_port;
memset(addr, 0, sizeof(*a4));
bzero(a4, sizeof(*a4));
a4->sin_family = AF_INET;
*len = sizeof(*a4);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.c,v 1.309 2010/08/05 13:08:42 djm Exp $ */
/* $OpenBSD: channels.c,v 1.310 2010/11/24 01:24:14 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -373,9 +373,6 @@ channel_close_fd(int *fdp)
static void
channel_close_fds(Channel *c)
{
debug3("channel %d: close_fds r %d w %d e %d",
c->self, c->rfd, c->wfd, c->efd);
channel_close_fd(&c->sock);
channel_close_fd(&c->rfd);
channel_close_fd(&c->wfd);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher-3des1.c,v 1.6 2006/08/03 03:34:42 deraadt Exp $ */
/* $OpenBSD: cipher-3des1.c,v 1.7 2010/10/01 23:05:32 djm Exp $ */
/*
* Copyright (c) 2003 Markus Friedl. All rights reserved.
*
@ -103,7 +103,8 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
}
static int
ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
LIBCRYPTO_EVP_INL_TYPE len)
{
struct ssh1_3des_ctx *c;

View File

@ -23,6 +23,7 @@
#if !defined(EVP_CTRL_SET_ACSS_MODE) && (OPENSSL_VERSION_NUMBER >= 0x00907000L)
#include "acss.h"
#include "openbsd-compat/openssl-compat.h"
#define data(ctx) ((EVP_ACSS_KEY *)(ctx)->cipher_data)
@ -43,7 +44,7 @@ acss_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
static int
acss_ciph(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
unsigned int inl)
LIBCRYPTO_EVP_INL_TYPE inl)
{
acss(&data(ctx)->ks,inl,in,out);
return 1;

View File

@ -72,7 +72,7 @@ ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
static int
ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
u_int len)
LIBCRYPTO_EVP_INL_TYPE len)
{
struct ssh_rijndael_ctx *c;
u_char buf[RIJNDAEL_BLOCKSIZE];

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher-bf1.c,v 1.5 2006/08/03 03:34:42 deraadt Exp $ */
/* $OpenBSD: cipher-bf1.c,v 1.6 2010/10/01 23:05:32 djm Exp $ */
/*
* Copyright (c) 2003 Markus Friedl. All rights reserved.
*
@ -76,10 +76,12 @@ static void bf_ssh1_init (EVP_CIPHER_CTX * ctx, const unsigned char *key,
}
#endif
static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
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, u_int len)
bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in,
LIBCRYPTO_EVP_INL_TYPE len)
{
int ret;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher-ctr.c,v 1.10 2006/08/03 03:34:42 deraadt Exp $ */
/* $OpenBSD: cipher-ctr.c,v 1.11 2010/10/01 23:05:32 djm Exp $ */
/*
* Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
*
@ -34,7 +34,7 @@
#endif
const EVP_CIPHER *evp_aes_128_ctr(void);
void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t);
struct ssh_aes_ctr_ctx
{
@ -48,7 +48,7 @@ struct ssh_aes_ctr_ctx
* (LSB at ctr[len-1], MSB at ctr[0])
*/
static void
ssh_ctr_inc(u_char *ctr, u_int len)
ssh_ctr_inc(u_char *ctr, size_t len)
{
int i;
@ -59,10 +59,10 @@ ssh_ctr_inc(u_char *ctr, u_int len)
static int
ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
u_int len)
LIBCRYPTO_EVP_INL_TYPE len)
{
struct ssh_aes_ctr_ctx *c;
u_int n = 0;
size_t n = 0;
u_char buf[AES_BLOCK_SIZE];
if (len == 0)
@ -113,7 +113,7 @@ ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
}
void
ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, size_t len)
{
struct ssh_aes_ctr_ctx *c;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.c,v 1.222 2010/07/19 09:15:12 djm Exp $ */
/* $OpenBSD: clientloop.c,v 1.231 2011/01/16 12:05:59 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -325,7 +325,7 @@ client_x11_get_proto(const char *display, const char *xauth_path,
if (trusted == 0) {
xauthdir = xmalloc(MAXPATHLEN);
xauthfile = xmalloc(MAXPATHLEN);
strlcpy(xauthdir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
mktemp_proto(xauthdir, MAXPATHLEN);
if (mkdtemp(xauthdir) != NULL) {
do_unlink = 1;
snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile",
@ -544,7 +544,7 @@ static void
server_alive_check(void)
{
if (packet_inc_alive_timeouts() > options.server_alive_count_max) {
logit("Timeout, server not responding.");
logit("Timeout, server %s not responding.", host);
cleanup_exit(255);
}
packet_start(SSH2_MSG_GLOBAL_REQUEST);
@ -1590,25 +1590,23 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
}
/* Output any buffered data for stdout. */
while (buffer_len(&stdout_buffer) > 0) {
len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
buffer_len(&stdout_buffer));
if (len <= 0) {
if (buffer_len(&stdout_buffer) > 0) {
len = atomicio(vwrite, fileno(stdout),
buffer_ptr(&stdout_buffer), buffer_len(&stdout_buffer));
if (len < 0 || (u_int)len != buffer_len(&stdout_buffer))
error("Write failed flushing stdout buffer.");
break;
}
buffer_consume(&stdout_buffer, len);
else
buffer_consume(&stdout_buffer, len);
}
/* Output any buffered data for stderr. */
while (buffer_len(&stderr_buffer) > 0) {
len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
buffer_len(&stderr_buffer));
if (len <= 0) {
if (buffer_len(&stderr_buffer) > 0) {
len = atomicio(vwrite, fileno(stderr),
buffer_ptr(&stderr_buffer), buffer_len(&stderr_buffer));
if (len < 0 || (u_int)len != buffer_len(&stderr_buffer))
error("Write failed flushing stderr buffer.");
break;
}
buffer_consume(&stderr_buffer, len);
else
buffer_consume(&stderr_buffer, len);
}
/* Clear and free any buffers. */
@ -1622,7 +1620,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",
obytes, ibytes, total_time);
(unsigned long long)obytes, (unsigned long long)ibytes, total_time);
if (total_time > 0)
verbose("Bytes per second: sent %.1f, received %.1f",
obytes / total_time, ibytes / total_time);
@ -1933,7 +1931,7 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt)
}
packet_check_eom();
}
if (reply) {
if (reply && c != NULL) {
packet_start(success ?
SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
packet_put_int(c->remote_id);
@ -1973,6 +1971,9 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
if ((c = channel_lookup(id)) == NULL)
fatal("client_session2_setup: channel %d: unknown channel", id);
packet_set_interactive(want_tty,
options.ip_qos_interactive, options.ip_qos_bulk);
if (want_tty) {
struct winsize ws;
@ -2129,5 +2130,6 @@ cleanup_exit(int i)
leave_non_blocking();
if (options.control_path != NULL && muxserver_sock != -1)
unlink(options.control_path);
ssh_kill_proxy_command();
_exit(i);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: compress.c,v 1.25 2006/08/06 01:13:32 stevesk Exp $ */
/* $OpenBSD: compress.c,v 1.26 2010/09/08 04:13:31 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -17,12 +17,13 @@
#include <sys/types.h>
#include <stdarg.h>
#include <zlib.h>
#include "log.h"
#include "buffer.h"
#include "compress.h"
#include <zlib.h>
z_stream incoming_stream;
z_stream outgoing_stream;
static int compress_init_send_called = 0;

View File

@ -125,6 +125,9 @@
/* Builtin PRNG command timeout */
#undef ENTROPY_TIMEOUT_MSEC
/* File names may not contain backslash characters */
#undef FILESYSTEM_NO_BACKSLASH
/* fsid_t has member val */
#undef FSID_HAS_VAL
@ -143,6 +146,9 @@
/* Define if your system glob() function has gl_matchc options in glob_t */
#undef GLOB_HAS_GL_MATCHC
/* Define if your system glob() function has gl_statv options in glob_t */
#undef GLOB_HAS_GL_STATV
/* Define this if you want GSSAPI support in the version 2 protocol */
#undef GSSAPI
@ -203,6 +209,9 @@
/* Define to 1 if you have the `bindresvport_sa' function. */
#undef HAVE_BINDRESVPORT_SA
/* Define to 1 if you have the `BN_is_prime_ex' function. */
#undef HAVE_BN_IS_PRIME_EX
/* Define to 1 if you have the <bsm/audit.h> header file. */
#undef HAVE_BSM_AUDIT_H
@ -311,6 +320,9 @@
/* Define to 1 if you have the `dirname' function. */
#undef HAVE_DIRNAME
/* Define to 1 if you have the `DSA_generate_parameters_ex' function. */
#undef HAVE_DSA_GENERATE_PARAMETERS_EX
/* Define to 1 if you have the <endian.h> header file. */
#undef HAVE_ENDIAN_H
@ -533,9 +545,15 @@
/* Define to 1 if the system has the type `in_port_t'. */
#undef HAVE_IN_PORT_T
/* Define if you have isblank(3C). */
#undef HAVE_ISBLANK
/* Define to 1 if you have the <lastlog.h> header file. */
#undef HAVE_LASTLOG_H
/* Define to 1 if you have the <libaudit.h> header file. */
#undef HAVE_LIBAUDIT_H
/* Define to 1 if you have the `bsm' library (-lbsm). */
#undef HAVE_LIBBSM
@ -738,6 +756,12 @@
/* Define to 1 if you have the `rresvport_af' function. */
#undef HAVE_RRESVPORT_AF
/* Define to 1 if you have the `RSA_generate_key_ex' function. */
#undef HAVE_RSA_GENERATE_KEY_EX
/* Define to 1 if you have the `RSA_get_default_method' function. */
#undef HAVE_RSA_GET_DEFAULT_METHOD
/* define if you have sa_family_t data type */
#undef HAVE_SA_FAMILY_T
@ -1044,6 +1068,9 @@
/* Define if you have ut_time in utmpx.h */
#undef HAVE_TIME_IN_UTMPX
/* Define to 1 if you have the `timingsafe_bcmp' function. */
#undef HAVE_TIMINGSAFE_BCMP
/* Define to 1 if you have the <tmpdir.h> header file. */
#undef HAVE_TMPDIR_H
@ -1259,6 +1286,9 @@
/* Define if EVP_DigestUpdate returns void */
#undef OPENSSL_EVP_DIGESTUPDATE_VOID
/* libcrypto includes complete ECC support */
#undef OPENSSL_HAS_ECC
/* libcrypto is missing AES 192 and 256 bit functions */
#undef OPENSSL_LOBOTOMISED_AES
@ -1390,6 +1420,9 @@
/* Use libedit for sftp */
#undef USE_LIBEDIT
/* Use Linux audit module */
#undef USE_LINUX_AUDIT
/* Enable OpenSSL engine support */
#undef USE_OPENSSL_ENGINE
@ -1402,6 +1435,9 @@
/* Define if you have Solaris process contracts */
#undef USE_SOLARIS_PROCESS_CONTRACTS
/* Define if you have Solaris projects */
#undef USE_SOLARIS_PROJECTS
/* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */
#undef WITH_ABBREV_NO_TTY

1088
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
# $Id: configure.ac,v 1.451 2010/08/16 03:15:23 dtucker Exp $
# $Id: configure.ac,v 1.469 2011/01/21 22:37:05 dtucker Exp $
#
# Copyright (c) 1999-2004 Damien Miller
#
@ -15,9 +15,21 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org)
AC_REVISION($Revision: 1.451 $)
AC_REVISION($Revision: 1.469 $)
AC_CONFIG_SRCDIR([ssh.c])
# local macros
AC_DEFUN([OPENSSH_CHECK_CFLAG_COMPILE], [{
AC_MSG_CHECKING([if $CC supports $1])
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_COMPILE_IFELSE([void main(void) { return 0; }],
[ AC_MSG_RESULT(yes) ],
[ AC_MSG_RESULT(no)
CFLAGS="$saved_CFLAGS" ]
)
}])
AC_CONFIG_HEADER(config.h)
AC_PROG_CC
AC_CANONICAL_HOST
@ -41,8 +53,24 @@ AC_PATH_PROG(TEST_MINUS_S_SH, bash)
AC_PATH_PROG(TEST_MINUS_S_SH, ksh)
AC_PATH_PROG(TEST_MINUS_S_SH, sh)
AC_PATH_PROG(SH, sh)
AC_PATH_PROG(GROFF, groff)
AC_PATH_PROG(NROFF, nroff)
AC_PATH_PROG(MANDOC, mandoc)
AC_SUBST(TEST_SHELL,sh)
dnl select manpage formatter
if test "x$MANDOC" != "x" ; then
MANFMT="$MANDOC"
elif test "x$NROFF" != "x" ; then
MANFMT="$NROFF -mandoc"
elif test "x$GROFF" != "x" ; then
MANFMT="$GROFF -mandoc -Tascii"
else
AC_MSG_WARN([no manpage formatted found])
MANFMT="false"
fi
AC_SUBST(MANFMT)
dnl for buildpkg.sh
AC_PATH_PROG(PATH_GROUPADD_PROG, groupadd, groupadd,
[/usr/sbin${PATH_SEPARATOR}/etc])
@ -97,20 +125,27 @@ AC_ARG_WITH(stackprotect,
use_stack_protector=0
fi ])
if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
CFLAGS="$CFLAGS -Wall -Wpointer-arith -Wuninitialized"
OPENSSH_CHECK_CFLAG_COMPILE([-Wall])
OPENSSH_CHECK_CFLAG_COMPILE([-Wpointer-arith])
OPENSSH_CHECK_CFLAG_COMPILE([-Wuninitialized])
OPENSSH_CHECK_CFLAG_COMPILE([-Wsign-compare])
OPENSSH_CHECK_CFLAG_COMPILE([-Wformat-security])
OPENSSH_CHECK_CFLAG_COMPILE([-Wno-pointer-sign])
OPENSSH_CHECK_CFLAG_COMPILE([-Wno-unused-result])
OPENSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing])
AC_MSG_CHECKING(gcc version)
GCC_VER=`$CC -v 2>&1 | $AWK '/gcc version /{print $3}'`
case $GCC_VER in
1.*) no_attrib_nonnull=1 ;;
2.8* | 2.9*)
CFLAGS="$CFLAGS -Wsign-compare"
no_attrib_nonnull=1
;;
2.*) no_attrib_nonnull=1 ;;
3.*) CFLAGS="$CFLAGS -Wsign-compare -Wformat-security" ;;
4.*) CFLAGS="$CFLAGS -Wsign-compare -Wno-pointer-sign -Wformat-security -fno-strict-aliasing" ;;
*) ;;
esac
AC_MSG_RESULT($GCC_VER)
AC_MSG_CHECKING(if $CC accepts -fno-builtin-memset)
saved_CFLAGS="$CFLAGS"
@ -333,6 +368,7 @@ AC_CHECK_HEADERS(sys/mount.h, [], [], [
# Messages for features tested for in target-specific section
SIA_MSG="no"
SPC_MSG="no"
SP_MSG="no"
# Check for some target-specific stuff
case "$host" in
@ -447,6 +483,7 @@ int main(void) { exit(0); }
[Define if your platform needs to skip post auth
file descriptor passing])
AC_DEFINE(SSH_IOBUFSZ, 65535, [Windows is sensitive to read buffer size])
AC_DEFINE(FILESYSTEM_NO_BACKSLASH, 1, [File names may not contain backslash characters])
;;
*-*-dgux*)
AC_DEFINE(IP_TOS_IS_BROKEN, 1,
@ -704,6 +741,17 @@ mips-sony-bsd|mips-sony-newsos4)
SPC_MSG="yes" ], )
],
)
AC_ARG_WITH(solaris-projects,
[ --with-solaris-projects Enable Solaris projects (experimental)],
[
AC_CHECK_LIB(project, setproject,
[ AC_DEFINE(USE_SOLARIS_PROJECTS, 1,
[Define if you have Solaris projects])
SSHDLIBS="$SSHDLIBS -lproject"
AC_SUBST(SSHDLIBS)
SP_MSG="yes" ], )
],
)
;;
*-*-sunos4*)
CPPFLAGS="$CPPFLAGS -DSUNOS4"
@ -1118,6 +1166,28 @@ AC_TRY_COMPILE(
]
)
# Check for g.gl_statv glob() extension
AC_MSG_CHECKING(for gl_statv and GLOB_KEEPSTAT extensions for glob)
AC_TRY_COMPILE(
[ #include <glob.h> ],
[
#ifndef GLOB_KEEPSTAT
#error "glob does not support GLOB_KEEPSTAT extension"
#endif
glob_t g;
g.gl_statv = NULL;
],
[
AC_DEFINE(GLOB_HAS_GL_STATV, 1,
[Define if your system glob() function has
gl_statv options in glob_t])
AC_MSG_RESULT(yes)
],
[
AC_MSG_RESULT(no)
]
)
AC_CHECK_DECLS(GLOB_NOMATCH, , , [#include <glob.h>])
AC_MSG_CHECKING([whether struct dirent allocates space for d_name])
@ -1273,7 +1343,7 @@ AC_ARG_WITH(libedit,
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
fi
fi
if test "x$use_pkgconfig_for_libedit" == "xyes"; then
if test "x$use_pkgconfig_for_libedit" = "xyes"; then
LIBEDIT=`$PKGCONFIG --libs-only-l libedit`
CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libedit`"
else
@ -1308,7 +1378,7 @@ int main(void)
AUDIT_MODULE=none
AC_ARG_WITH(audit,
[ --with-audit=module Enable EXPERIMENTAL audit support (modules=debug,bsm)],
[ --with-audit=module Enable audit support (modules=debug,bsm,linux)],
[
AC_MSG_CHECKING(for supported audit module)
case "$withval" in
@ -1332,10 +1402,18 @@ AC_ARG_WITH(audit,
AC_CHECK_FUNCS(getaudit_addr aug_get_machine)
AC_DEFINE(USE_BSM_AUDIT, 1, [Use BSM audit module])
;;
linux)
AC_MSG_RESULT(linux)
AUDIT_MODULE=linux
dnl Checks for headers, libs and functions
AC_CHECK_HEADERS(libaudit.h)
SSHDLIBS="$SSHDLIBS -laudit"
AC_DEFINE(USE_LINUX_AUDIT, 1, [Use Linux audit module])
;;
debug)
AUDIT_MODULE=debug
AC_MSG_RESULT(debug)
AC_DEFINE(SSH_AUDIT_EVENTS, 1, Use audit debugging module)
AC_DEFINE(SSH_AUDIT_EVENTS, 1, [Use audit debugging module])
;;
no)
AC_MSG_RESULT(no)
@ -1434,6 +1512,7 @@ AC_CHECK_FUNCS( \
swap32 \
sysconf \
tcgetpgrp \
timingsafe_bcmp \
truncate \
unsetenv \
updwtmpx \
@ -1444,6 +1523,17 @@ AC_CHECK_FUNCS( \
waitpid \
)
AC_LINK_IFELSE(
[
#include <ctype.h>
int main(void)
{
return (isblank('a'));
}
],
[AC_DEFINE(HAVE_ISBLANK, 1, [Define if you have isblank(3C).])
])
# PKCS#11 support requires dlopen() and co
AC_SEARCH_LIBS(dlopen, dl,
AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support])
@ -2090,6 +2180,8 @@ int main(void) { SSLeay_add_all_algorithms(); }
]
)
AC_CHECK_FUNCS(RSA_generate_key_ex DSA_generate_parameters_ex BN_is_prime_ex RSA_get_default_method)
AC_ARG_WITH(ssl-engine,
[ --with-ssl-engine Enable OpenSSL (hardware) ENGINE support ],
[ if test "x$withval" != "xno" ; then
@ -2156,7 +2248,43 @@ if test "x$check_for_libcrypt_later" = "x1"; then
fi
# Search for SHA256 support in libc and/or OpenSSL
AC_CHECK_FUNCS(SHA256_Update EVP_sha256)
AC_CHECK_FUNCS(SHA256_Update EVP_sha256, [TEST_SSH_SHA256=yes],
[TEST_SSH_SHA256=no])
AC_SUBST(TEST_SSH_SHA256)
# Check complete ECC support in OpenSSL
AC_MSG_CHECKING([whether OpenSSL has complete ECC support])
AC_LINK_IFELSE(
[AC_LANG_SOURCE([[
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#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(void) {
EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1);
const EVP_MD *m = EVP_sha512(); /* We need this too */
}
]])],
[
AC_MSG_RESULT(yes)
AC_DEFINE(OPENSSL_HAS_ECC, 1,
[libcrypto includes complete ECC support])
TEST_SSH_ECC=yes
COMMENT_OUT_ECC=""
],
[
AC_MSG_RESULT(no)
TEST_SSH_ECC=no
COMMENT_OUT_ECC="#no ecc#"
]
)
AC_SUBST(TEST_SSH_ECC)
AC_SUBST(COMMENT_OUT_ECC)
saved_LIBS="$LIBS"
AC_CHECK_LIB(iaf, ia_openinfo, [
@ -3443,10 +3571,12 @@ AC_ARG_WITH(kerberos5,
[ char *tmp = heimdal_version; ],
[ AC_MSG_RESULT(yes)
AC_DEFINE(HEIMDAL)
K5LIBS="-lkrb5 -ldes"
K5LIBS="-lkrb5"
K5LIBS="$K5LIBS -lcom_err -lasn1"
AC_CHECK_LIB(roken, net_write,
[K5LIBS="$K5LIBS -lroken"])
AC_CHECK_LIB(des, des_cbc_encrypt,
[K5LIBS="$K5LIBS -ldes"])
],
[ AC_MSG_RESULT(no)
K5LIBS="-lkrb5 -lk5crypto -lcom_err"
@ -4191,6 +4321,7 @@ echo " TCP Wrappers support: $TCPW_MSG"
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
echo " Solaris process contract support: $SPC_MSG"
echo " Solaris project support: $SP_MSG"
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
echo " BSD Auth support: $BSD_AUTH_MSG"

View File

@ -16,7 +16,7 @@
#old cvs stuff. please update before use. may be deprecated.
%define use_stable 1
%define version 5.6p1
%define version 5.7p1
%if %{use_stable}
%define cvs %{nil}
%define release 1
@ -57,7 +57,7 @@ BuildRequires : XFree86-imake
# %{use_stable}==0: :pserver:cvs@bass.directhit.com:/cvs/openssh_cvs
Source0: see-above:/.../openssh-%{version}.tar.gz
%if %{use_stable}
Source1: see-above:/.../openssh-%{version}.tar.gz.sig
Source1: see-above:/.../openssh-%{version}.tar.gz.asc
%endif
Source2: http://www.jmknoble.net/software/%{xsa}/%{askpass}.tar.gz
Source3: http://www.openssh.com/faq.html
@ -182,7 +182,7 @@ CFLAGS="$RPM_OPT_FLAGS" \
--with-privsep-path=%{_var}/empty/sshd \
#leave this line for easy edits.
%__make CFLAGS="$RPM_OPT_FLAGS"
%__make
cd %{askpass}
%configure \
@ -356,7 +356,11 @@ fi
%ChangeLog
* Tue Jan 18 2011 Tim Rice <tim@multitalents.net>
- Use CFLAGS from Makefile instead of RPM so build completes.
- Signatures were changed to .asc since 4.1p1.
* Mon Jan 01 1998 ...
Template Version: 1.31
$Id: openssh.spec,v 1.71 2010/08/08 16:32:09 djm Exp $
$Id: openssh.spec,v 1.73 2011/01/22 09:23:33 djm Exp $

View File

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

View File

@ -104,7 +104,7 @@ start()
do_dsa_keygen
echo -n $"Starting $prog:"
initlog -c "$SSHD $OPTIONS" && success || failure
$SSHD $OPTIONS && success || failure
RETVAL=$?
[ "$RETVAL" = 0 ] && touch /var/lock/subsys/sshd
echo

View File

@ -13,7 +13,7 @@
Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation
Name: openssh
Version: 5.6p1
Version: 5.7p1
URL: http://www.openssh.com/
Release: 1
Source0: openssh-%{version}.tar.gz

View File

@ -25,7 +25,7 @@
#ifndef _DEFINES_H
#define _DEFINES_H
/* $Id: defines.h,v 1.160 2010/04/09 08:13:27 dtucker Exp $ */
/* $Id: defines.h,v 1.164 2011/01/17 10:15:31 dtucker Exp $ */
/* Constants */
@ -42,6 +42,9 @@ enum
# define SHUT_RDWR SHUT_RDWR
#endif
/*
* Definitions for IP type of service (ip_tos)
*/
#ifndef IPTOS_LOWDELAY
# define IPTOS_LOWDELAY 0x10
# define IPTOS_THROUGHPUT 0x08
@ -50,6 +53,40 @@ enum
# define IPTOS_MINCOST IPTOS_LOWCOST
#endif /* IPTOS_LOWDELAY */
/*
* Definitions for DiffServ Codepoints as per RFC2474
*/
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#ifndef IPTOS_DSCP_AF11
# define IPTOS_DSCP_AF11 0x28
# define IPTOS_DSCP_AF12 0x30
# define IPTOS_DSCP_AF13 0x38
# define IPTOS_DSCP_AF21 0x48
# define IPTOS_DSCP_AF22 0x50
# define IPTOS_DSCP_AF23 0x58
# define IPTOS_DSCP_AF31 0x68
# define IPTOS_DSCP_AF32 0x70
# define IPTOS_DSCP_AF33 0x78
# define IPTOS_DSCP_AF41 0x88
# define IPTOS_DSCP_AF42 0x90
# define IPTOS_DSCP_AF43 0x98
# define IPTOS_DSCP_EF 0xb8
#endif /* IPTOS_DSCP_AF11 */
#ifndef IPTOS_DSCP_CS0
# define IPTOS_DSCP_CS0 0x00
# define IPTOS_DSCP_CS1 0x20
# define IPTOS_DSCP_CS2 0x40
# define IPTOS_DSCP_CS3 0x60
# define IPTOS_DSCP_CS4 0x80
# define IPTOS_DSCP_CS5 0xa0
# define IPTOS_DSCP_CS6 0xc0
# define IPTOS_DSCP_CS7 0xe0
#endif /* IPTOS_DSCP_CS0 */
#ifndef IPTOS_DSCP_EF
# define IPTOS_DSCP_EF 0xb8
#endif /* IPTOS_DSCP_EF */
#ifndef MAXPATHLEN
# ifdef PATH_MAX
# define MAXPATHLEN PATH_MAX
@ -256,6 +293,10 @@ typedef unsigned int size_t;
# define SIZE_T_MAX UINT_MAX
#endif /* HAVE_SIZE_T */
#ifndef SIZE_MAX
#define SIZE_MAX SIZE_T_MAX
#endif
#ifndef HAVE_SSIZE_T
typedef int ssize_t;
# define HAVE_SSIZE_T
@ -566,6 +607,11 @@ struct winsize {
# define CUSTOM_SSH_AUDIT_EVENTS
#endif
#ifdef USE_LINUX_AUDIT
# define SSH_AUDIT_EVENTS
# define CUSTOM_SSH_AUDIT_EVENTS
#endif
#if !defined(HAVE___func__) && defined(HAVE___FUNCTION__)
# define __func__ __FUNCTION__
#elif !defined(HAVE___func__)

3
dns.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dns.c,v 1.26 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: dns.c,v 1.27 2010/08/31 11:54:45 djm Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@ -86,6 +86,7 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
case KEY_DSA:
*algorithm = SSHFP_KEY_DSA;
break;
/* XXX KEY_ECDSA */
default:
*algorithm = SSHFP_KEY_RESERVED; /* 0 */
}

View File

@ -157,7 +157,7 @@ init_rng(void)
*/
if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L)
fatal("OpenSSL version mismatch. Built against %lx, you "
"have %lx", OPENSSL_VERSION_NUMBER, SSLeay());
"have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
#ifndef OPENSSL_PRNG_ONLY
original_uid = getuid();

View File

@ -1,4 +1,4 @@
/* $OpenBSD: hostfile.c,v 1.48 2010/03/04 10:36:03 djm Exp $ */
/* $OpenBSD: hostfile.c,v 1.50 2010/12/04 13:31:37 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -56,6 +56,12 @@
#include "key.h"
#include "hostfile.h"
#include "log.h"
#include "misc.h"
struct hostkeys {
struct hostkey_entry *entries;
u_int num_entries;
};
static int
extract_salt(const char *s, u_int l, char *salt, size_t salt_len)
@ -164,26 +170,28 @@ hostfile_read_key(char **cpp, u_int *bitsp, Key *ret)
/* Return results. */
*cpp = cp;
*bitsp = key_size(ret);
if (bitsp != NULL)
*bitsp = key_size(ret);
return 1;
}
static int
hostfile_check_key(int bits, const Key *key, const char *host, const char *filename, int linenum)
hostfile_check_key(int bits, const Key *key, const char *host,
const char *filename, u_long linenum)
{
if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL)
return 1;
if (bits != BN_num_bits(key->rsa->n)) {
logit("Warning: %s, line %d: keysize mismatch for host %s: "
logit("Warning: %s, line %lu: keysize mismatch for host %s: "
"actual %d vs. announced %d.",
filename, linenum, host, BN_num_bits(key->rsa->n), bits);
logit("Warning: replace %d with %d in %s, line %d.",
logit("Warning: replace %d with %d in %s, line %lu.",
bits, BN_num_bits(key->rsa->n), filename, linenum);
}
return 1;
}
static enum { MRK_ERROR, MRK_NONE, MRK_REVOKE, MRK_CA }
static HostkeyMarker
check_markers(char **cpp)
{
char marker[32], *sp, *cp = *cpp;
@ -218,49 +226,32 @@ check_markers(char **cpp)
return ret;
}
/*
* Checks whether the given host (which must be in all lowercase) is already
* in the list of our known hosts. Returns HOST_OK if the host is known and
* has the specified key, HOST_NEW if the host is not known, and HOST_CHANGED
* if the host is known but used to have a different host key.
*
* If no 'key' has been specified and a key of type 'keytype' is known
* for the specified host, then HOST_FOUND is returned.
*/
struct hostkeys *
init_hostkeys(void)
{
struct hostkeys *ret = xcalloc(1, sizeof(*ret));
static HostStatus
check_host_in_hostfile_by_key_or_type(const char *filename,
const char *host, const Key *key, int keytype, Key *found,
int want_revocation, int *numret)
ret->entries = NULL;
return ret;
}
void
load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path)
{
FILE *f;
char line[8192];
int want, have, linenum = 0, want_cert = key_is_cert(key);
u_int kbits;
u_long linenum = 0, num_loaded = 0;
char *cp, *cp2, *hashed_host;
HostStatus end_return;
HostkeyMarker marker;
Key *key;
int kbits;
debug3("check_host_in_hostfile: host %s filename %s", host, filename);
if (want_revocation && (key == NULL || keytype != 0 || found != NULL))
fatal("%s: invalid arguments", __func__);
/* Open the file containing the list of known hosts. */
f = fopen(filename, "r");
if (!f)
return HOST_NEW;
/*
* Return value when the loop terminates. This is set to
* HOST_CHANGED if we have seen a different key for the host and have
* not found the proper one.
*/
end_return = HOST_NEW;
/* Go through the file. */
while (fgets(line, sizeof(line), f)) {
if ((f = fopen(path, "r")) == NULL)
return;
debug3("%s: loading entries for host \"%.100s\" from file \"%s\"",
__func__, host, path);
while (read_keyfile_line(f, path, line, sizeof(line), &linenum) == 0) {
cp = line;
linenum++;
/* Skip any leading whitespace, comments and empty lines. */
for (; *cp == ' ' || *cp == '\t'; cp++)
@ -268,19 +259,11 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
if (!*cp || *cp == '#' || *cp == '\n')
continue;
if (want_revocation)
want = MRK_REVOKE;
else if (want_cert)
want = MRK_CA;
else
want = MRK_NONE;
if ((have = check_markers(&cp)) == MRK_ERROR) {
verbose("%s: invalid marker at %s:%d",
__func__, filename, linenum);
continue;
} else if (want != have)
if ((marker = check_markers(&cp)) == MRK_ERROR) {
verbose("%s: invalid marker at %s:%lu",
__func__, path, linenum);
continue;
}
/* Find the end of the host name portion. */
for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)
@ -292,8 +275,8 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
continue;
hashed_host = host_hash(host, cp, (u_int) (cp2 - cp));
if (hashed_host == NULL) {
debug("Invalid hashed host line %d of %s",
linenum, filename);
debug("Invalid hashed host line %lu of %s",
linenum, path);
continue;
}
if (strncmp(hashed_host, cp, (u_int) (cp2 - cp)) != 0)
@ -303,98 +286,167 @@ check_host_in_hostfile_by_key_or_type(const char *filename,
/* Got a match. Skip host name. */
cp = cp2;
if (want_revocation)
found = key_new(KEY_UNSPEC);
/*
* Extract the key from the line. This will skip any leading
* whitespace. Ignore badly formatted lines.
*/
if (!hostfile_read_key(&cp, &kbits, found))
continue;
if (numret != NULL)
*numret = linenum;
if (key == NULL) {
/* we found a key of the requested type */
if (found->type == keytype) {
fclose(f);
return HOST_FOUND;
key = key_new(KEY_UNSPEC);
if (!hostfile_read_key(&cp, &kbits, key)) {
key_free(key);
key = key_new(KEY_RSA1);
if (!hostfile_read_key(&cp, &kbits, key)) {
key_free(key);
continue;
}
continue;
}
if (!hostfile_check_key(kbits, found, host, filename, linenum))
if (!hostfile_check_key(kbits, key, host, path, linenum))
continue;
if (want_revocation) {
if (key_is_cert(key) &&
key_equal_public(key->cert->signature_key, found)) {
verbose("check_host_in_hostfile: revoked CA "
"line %d", linenum);
key_free(found);
return HOST_REVOKED;
}
if (key_equal_public(key, found)) {
verbose("check_host_in_hostfile: revoked key "
"line %d", linenum);
key_free(found);
return HOST_REVOKED;
}
key_free(found);
continue;
}
/* Check if the current key is the same as the given key. */
if (want_cert && key_equal(key->cert->signature_key, found)) {
/* Found CA cert for key */
debug3("check_host_in_hostfile: CA match line %d",
linenum);
fclose(f);
return HOST_OK;
} else if (!want_cert && key_equal(key, found)) {
/* Found identical key */
debug3("check_host_in_hostfile: match line %d", linenum);
fclose(f);
return HOST_OK;
}
/*
* They do not match. We will continue to go through the
* file; however, we note that we will not return that it is
* new.
*/
end_return = HOST_CHANGED;
debug3("%s: found %skey type %s in file %s:%lu", __func__,
marker == MRK_NONE ? "" :
(marker == MRK_CA ? "ca " : "revoked "),
key_type(key), path, linenum);
hostkeys->entries = xrealloc(hostkeys->entries,
hostkeys->num_entries + 1, sizeof(*hostkeys->entries));
hostkeys->entries[hostkeys->num_entries].host = xstrdup(host);
hostkeys->entries[hostkeys->num_entries].file = xstrdup(path);
hostkeys->entries[hostkeys->num_entries].line = linenum;
hostkeys->entries[hostkeys->num_entries].key = key;
hostkeys->entries[hostkeys->num_entries].marker = marker;
hostkeys->num_entries++;
num_loaded++;
}
/* Clear variables and close the file. */
debug3("%s: loaded %lu keys", __func__, num_loaded);
fclose(f);
return;
}
/*
* Return either HOST_NEW or HOST_CHANGED, depending on whether we
* saw a different key for the host.
*/
return end_return;
void
free_hostkeys(struct hostkeys *hostkeys)
{
u_int i;
for (i = 0; i < hostkeys->num_entries; i++) {
xfree(hostkeys->entries[i].host);
xfree(hostkeys->entries[i].file);
key_free(hostkeys->entries[i].key);
bzero(hostkeys->entries + i, sizeof(*hostkeys->entries));
}
if (hostkeys->entries != NULL)
xfree(hostkeys->entries);
hostkeys->entries = NULL;
hostkeys->num_entries = 0;
xfree(hostkeys);
}
static int
check_key_not_revoked(struct hostkeys *hostkeys, Key *k)
{
int is_cert = key_is_cert(k);
u_int i;
for (i = 0; i < hostkeys->num_entries; i++) {
if (hostkeys->entries[i].marker != MRK_REVOKE)
continue;
if (key_equal_public(k, hostkeys->entries[i].key))
return -1;
if (is_cert &&
key_equal_public(k->cert->signature_key,
hostkeys->entries[i].key))
return -1;
}
return 0;
}
/*
* Match keys against a specified key, or look one up by key type.
*
* If looking for a keytype (key == NULL) and one is found then return
* HOST_FOUND, otherwise HOST_NEW.
*
* If looking for a key (key != NULL):
* 1. If the key is a cert and a matching CA is found, return HOST_OK
* 2. If the key is not a cert and a matching key is found, return HOST_OK
* 3. If no key matches but a key with a different type is found, then
* return HOST_CHANGED
* 4. If no matching keys are found, then return HOST_NEW.
*
* Finally, check any found key is not revoked.
*/
static HostStatus
check_hostkeys_by_key_or_type(struct hostkeys *hostkeys,
Key *k, int keytype, const struct hostkey_entry **found)
{
u_int i;
HostStatus end_return = HOST_NEW;
int want_cert = key_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) {
if (hostkeys->entries[i].key->type != keytype)
continue;
end_return = HOST_FOUND;
if (found != NULL)
*found = hostkeys->entries + i;
k = hostkeys->entries[i].key;
break;
}
if (want_cert) {
if (key_equal_public(k->cert->signature_key,
hostkeys->entries[i].key)) {
/* A matching CA exists */
end_return = HOST_OK;
if (found != NULL)
*found = hostkeys->entries + i;
break;
}
} else {
if (key_equal(k, hostkeys->entries[i].key)) {
end_return = HOST_OK;
if (found != NULL)
*found = hostkeys->entries + i;
break;
}
/* A non-maching key exists */
end_return = HOST_CHANGED;
if (found != NULL)
*found = hostkeys->entries + i;
}
}
if (check_key_not_revoked(hostkeys, k) != 0) {
end_return = HOST_REVOKED;
if (found != NULL)
*found = NULL;
}
return end_return;
}
HostStatus
check_host_in_hostfile(const char *filename, const char *host, const Key *key,
Key *found, int *numret)
check_key_in_hostkeys(struct hostkeys *hostkeys, Key *key,
const struct hostkey_entry **found)
{
if (key == NULL)
fatal("no key to look up");
if (check_host_in_hostfile_by_key_or_type(filename, host,
key, 0, NULL, 1, NULL) == HOST_REVOKED)
return HOST_REVOKED;
return check_host_in_hostfile_by_key_or_type(filename, host, key, 0,
found, 0, numret);
return check_hostkeys_by_key_or_type(hostkeys, key, 0, found);
}
int
lookup_key_in_hostfile_by_type(const char *filename, const char *host,
int keytype, Key *found, int *numret)
lookup_key_in_hostkeys_by_type(struct hostkeys *hostkeys, int keytype,
const struct hostkey_entry **found)
{
return (check_host_in_hostfile_by_key_or_type(filename, host, NULL,
keytype, found, 0, numret) == HOST_FOUND);
return (check_hostkeys_by_key_or_type(hostkeys, NULL, keytype,
found) == HOST_FOUND);
}
/*

View File

@ -1,4 +1,4 @@
/* $OpenBSD: hostfile.h,v 1.18 2010/03/04 10:36:03 djm Exp $ */
/* $OpenBSD: hostfile.h,v 1.19 2010/11/29 23:45:51 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -18,12 +18,30 @@ typedef enum {
HOST_OK, HOST_NEW, HOST_CHANGED, HOST_REVOKED, HOST_FOUND
} HostStatus;
typedef enum {
MRK_ERROR, MRK_NONE, MRK_REVOKE, MRK_CA
} HostkeyMarker;
struct hostkey_entry {
char *host;
char *file;
u_long line;
Key *key;
HostkeyMarker marker;
};
struct hostkeys;
struct hostkeys *init_hostkeys(void);
void load_hostkeys(struct hostkeys *, const char *, const char *);
void free_hostkeys(struct hostkeys *);
HostStatus check_key_in_hostkeys(struct hostkeys *, Key *,
const struct hostkey_entry **);
int lookup_key_in_hostkeys_by_type(struct hostkeys *, int,
const struct hostkey_entry **);
int hostfile_read_key(char **, u_int *, Key *);
HostStatus check_host_in_hostfile(const char *, const char *,
const Key *, Key *, int *);
int add_host_to_hostfile(const char *, const char *, const Key *, int);
int lookup_key_in_hostfile_by_type(const char *, const char *,
int, Key *, int *);
int add_host_to_hostfile(const char *, const char *, const Key *, int);
#define HASH_MAGIC "|1|"
#define HASH_DELIM '|'

View File

@ -30,7 +30,7 @@
# include <bstring.h>
#endif
#if defined(HAVE_GLOB_H) && defined(GLOB_HAS_ALTDIRFUNC) && \
defined(GLOB_HAS_GL_MATCHC) && \
defined(GLOB_HAS_GL_MATCHC) && defined(GLOB_HAS_GL_STATV) && \
defined(HAVE_DECL_GLOB_NOMATCH) && HAVE_DECL_GLOB_NOMATCH != 0 && \
!defined(BROKEN_GLOB)
# include <glob.h>

View File

@ -1,4 +1,4 @@
/* $OpenBSD: jpake.c,v 1.4 2010/07/13 23:13:16 djm Exp $ */
/* $OpenBSD: jpake.c,v 1.6 2010/09/20 04:54:07 djm Exp $ */
/*
* Copyright (c) 2008 Damien Miller. All rights reserved.
*
@ -45,6 +45,7 @@
#include "packet.h"
#include "dispatch.h"
#include "log.h"
#include "misc.h"
#include "jpake.h"
#include "schnorr.h"
@ -257,8 +258,12 @@ jpake_step2(struct modp_group *grp, BIGNUM *s,
/* Validate peer's step 1 values */
if (BN_cmp(theirpub1, BN_value_one()) <= 0)
fatal("%s: theirpub1 <= 1", __func__);
if (BN_cmp(theirpub1, grp->p) >= 0)
fatal("%s: theirpub1 >= p", __func__);
if (BN_cmp(theirpub2, BN_value_one()) <= 0)
fatal("%s: theirpub2 <= 1", __func__);
if (BN_cmp(theirpub2, grp->p) >= 0)
fatal("%s: theirpub2 >= p", __func__);
if (schnorr_verify_buf(grp->p, grp->q, grp->g, theirpub1,
theirid, theirid_len, theirpub1_proof, theirpub1_proof_len) != 1)
@ -363,6 +368,8 @@ jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
/* Validate step 2 values */
if (BN_cmp(step2_val, BN_value_one()) <= 0)
fatal("%s: step2_val <= 1", __func__);
if (BN_cmp(step2_val, grp->p) >= 0)
fatal("%s: step2_val >= p", __func__);
/*
* theirpriv2_s_proof is calculated with a different generator:

40
kex.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.c,v 1.82 2009/10/24 11:13:54 andreas Exp $ */
/* $OpenBSD: kex.c,v 1.86 2010/09/22 05:01:29 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@ -62,6 +62,34 @@ extern const EVP_MD *evp_ssh_sha256(void);
static void kex_kexinit_finish(Kex *);
static void kex_choose_conf(Kex *);
/* Validate KEX method name list */
int
kex_names_valid(const char *names)
{
char *s, *cp, *p;
if (names == NULL || strcmp(names, "") == 0)
return 0;
s = cp = xstrdup(names);
for ((p = strsep(&cp, ",")); p && *p != '\0';
(p = strsep(&cp, ","))) {
if (strcmp(p, KEX_DHGEX_SHA256) != 0 &&
strcmp(p, KEX_DHGEX_SHA1) != 0 &&
strcmp(p, KEX_DH14) != 0 &&
strcmp(p, KEX_DH1) != 0 &&
(strncmp(p, KEX_ECDH_SHA2_STEM,
sizeof(KEX_ECDH_SHA2_STEM) - 1) != 0 ||
kex_ecdh_name_to_nid(p) == -1)) {
error("Unsupported KEX algorithm \"%.100s\"", p);
xfree(s);
return 0;
}
}
debug3("kex names ok: [%s]", names);
xfree(s);
return 1;
}
/* put algorithm proposal into buffer */
static void
kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
@ -98,7 +126,7 @@ kex_buf2prop(Buffer *raw, int *first_kex_follows)
buffer_get_char(&b);
/* extract kex init proposal strings */
for (i = 0; i < PROPOSAL_MAX; i++) {
proposal[i] = buffer_get_string(&b,NULL);
proposal[i] = buffer_get_cstring(&b,NULL);
debug2("kex_parse_kexinit: %s", proposal[i]);
}
/* first kex follows / reserved */
@ -325,6 +353,10 @@ choose_kex(Kex *k, char *client, char *server)
} else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) {
k->kex_type = KEX_DH_GEX_SHA256;
k->evp_md = evp_ssh_sha256();
} else if (strncmp(k->name, KEX_ECDH_SHA2_STEM,
sizeof(KEX_ECDH_SHA2_STEM) - 1) == 0) {
k->kex_type = KEX_ECDH_SHA2;
k->evp_md = kex_ecdh_name_to_evpmd(k->name);
#endif
} else
fatal("bad kex alg %s", k->name);
@ -559,11 +591,11 @@ derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
memset(&md, 0, sizeof(md));
}
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
void
dump_digest(char *msg, u_char *digest, int len)
{
u_int i;
int i;
fprintf(stderr, "%s\n", msg);
for (i = 0; i < len; i++) {

25
kex.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.h,v 1.49 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: kex.h,v 1.52 2010/09/22 05:01:29 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -29,6 +29,9 @@
#include <signal.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#ifdef OPENSSL_HAS_ECC
#include <openssl/ec.h>
#endif
#define KEX_COOKIE_LEN 16
@ -37,6 +40,8 @@
#define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1"
#define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256"
#define KEX_RESUME "resume@appgate.com"
/* The following represents the family of ECDH methods */
#define KEX_ECDH_SHA2_STEM "ecdh-sha2-"
#define COMP_NONE 0
#define COMP_ZLIB 1
@ -67,6 +72,7 @@ enum kex_exchange {
KEX_DH_GRP14_SHA1,
KEX_DH_GEX_SHA1,
KEX_DH_GEX_SHA256,
KEX_ECDH_SHA2,
KEX_MAX
};
@ -132,6 +138,8 @@ struct Kex {
void (*kex[KEX_MAX])(Kex *);
};
int kex_names_valid(const char *);
Kex *kex_setup(char *[PROPOSAL_MAX]);
void kex_finish(Kex *);
@ -145,6 +153,8 @@ void kexdh_client(Kex *);
void kexdh_server(Kex *);
void kexgex_client(Kex *);
void kexgex_server(Kex *);
void kexecdh_client(Kex *);
void kexecdh_server(Kex *);
void
kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
@ -153,11 +163,22 @@ void
kexgex_hash(const EVP_MD *, char *, char *, char *, int, char *,
int, u_char *, int, int, int, int, BIGNUM *, BIGNUM *, BIGNUM *,
BIGNUM *, BIGNUM *, u_char **, u_int *);
#ifdef OPENSSL_HAS_ECC
void
kex_ecdh_hash(const EVP_MD *, const EC_GROUP *, char *, char *, char *, int,
char *, int, u_char *, int, const EC_POINT *, const EC_POINT *,
const BIGNUM *, u_char **, u_int *);
int kex_ecdh_name_to_nid(const char *);
const EVP_MD *kex_ecdh_name_to_evpmd(const char *);
#else
# define kex_ecdh_name_to_nid(x) (-1)
# define kex_ecdh_name_to_evpmd(x) (NULL)
#endif
void
derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]);
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
#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: kexdhc.c,v 1.11 2006/11/06 21:25:28 markus Exp $ */
/* $OpenBSD: kexdhc.c,v 1.12 2010/11/10 01:33:07 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@ -27,6 +27,8 @@
#include <sys/types.h>
#include <openssl/dh.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexdhs.c,v 1.11 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: kexdhs.c,v 1.12 2010/11/10 01:33:07 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@ -31,6 +31,8 @@
#include <string.h>
#include <signal.h>
#include <openssl/dh.h>
#include "xmalloc.h"
#include "buffer.h"
#include "key.h"

117
kexecdh.c Normal file
View File

@ -0,0 +1,117 @@
/* $OpenBSD: kexecdh.c,v 1.3 2010/09/22 05:01:29 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef OPENSSL_HAS_ECC
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include "buffer.h"
#include "ssh2.h"
#include "key.h"
#include "cipher.h"
#include "kex.h"
#include "log.h"
int
kex_ecdh_name_to_nid(const char *kexname)
{
if (strlen(kexname) < sizeof(KEX_ECDH_SHA2_STEM) - 1)
fatal("%s: kexname too short \"%s\"", __func__, kexname);
return key_curve_name_to_nid(kexname + sizeof(KEX_ECDH_SHA2_STEM) - 1);
}
const EVP_MD *
kex_ecdh_name_to_evpmd(const char *kexname)
{
int nid = kex_ecdh_name_to_nid(kexname);
if (nid == -1)
fatal("%s: unsupported ECDH curve \"%s\"", __func__, kexname);
return key_ec_nid_to_evpmd(nid);
}
void
kex_ecdh_hash(
const EVP_MD *evp_md,
const EC_GROUP *ec_group,
char *client_version_string,
char *server_version_string,
char *ckexinit, int ckexinitlen,
char *skexinit, int skexinitlen,
u_char *serverhostkeyblob, int sbloblen,
const EC_POINT *client_dh_pub,
const EC_POINT *server_dh_pub,
const BIGNUM *shared_secret,
u_char **hash, u_int *hashlen)
{
Buffer b;
EVP_MD_CTX md;
static u_char digest[EVP_MAX_MD_SIZE];
buffer_init(&b);
buffer_put_cstring(&b, client_version_string);
buffer_put_cstring(&b, server_version_string);
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
buffer_put_int(&b, ckexinitlen+1);
buffer_put_char(&b, SSH2_MSG_KEXINIT);
buffer_append(&b, ckexinit, ckexinitlen);
buffer_put_int(&b, skexinitlen+1);
buffer_put_char(&b, SSH2_MSG_KEXINIT);
buffer_append(&b, skexinit, skexinitlen);
buffer_put_string(&b, serverhostkeyblob, sbloblen);
buffer_put_ecpoint(&b, ec_group, client_dh_pub);
buffer_put_ecpoint(&b, ec_group, server_dh_pub);
buffer_put_bignum2(&b, shared_secret);
#ifdef DEBUG_KEX
buffer_dump(&b);
#endif
EVP_DigestInit(&md, evp_md);
EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
EVP_DigestFinal(&md, digest, NULL);
buffer_free(&b);
#ifdef DEBUG_KEX
dump_digest("hash", digest, EVP_MD_size(evp_md));
#endif
*hash = digest;
*hashlen = EVP_MD_size(evp_md);
}
#endif /* OPENSSL_HAS_ECC */

168
kexecdhc.c Normal file
View File

@ -0,0 +1,168 @@
/* $OpenBSD: kexecdhc.c,v 1.2 2010/09/22 05:01:29 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include "xmalloc.h"
#include "buffer.h"
#include "key.h"
#include "cipher.h"
#include "kex.h"
#include "log.h"
#include "packet.h"
#include "dh.h"
#include "ssh2.h"
#ifdef OPENSSL_HAS_ECC
#include <openssl/ecdh.h>
void
kexecdh_client(Kex *kex)
{
EC_KEY *client_key;
EC_POINT *server_public;
const EC_GROUP *group;
BIGNUM *shared_secret;
Key *server_host_key;
u_char *server_host_key_blob = NULL, *signature = NULL;
u_char *kbuf, *hash;
u_int klen, slen, sbloblen, hashlen;
int curve_nid;
if ((curve_nid = kex_ecdh_name_to_nid(kex->name)) == -1)
fatal("%s: unsupported ECDH curve \"%s\"", __func__, kex->name);
if ((client_key = EC_KEY_new_by_curve_name(curve_nid)) == NULL)
fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
if (EC_KEY_generate_key(client_key) != 1)
fatal("%s: EC_KEY_generate_key failed", __func__);
group = EC_KEY_get0_group(client_key);
packet_start(SSH2_MSG_KEX_ECDH_INIT);
packet_put_ecpoint(group, EC_KEY_get0_public_key(client_key));
packet_send();
debug("sending SSH2_MSG_KEX_ECDH_INIT");
#ifdef DEBUG_KEXECDH
fputs("client private key:\n", stderr);
key_dump_ec_key(client_key);
#endif
debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
packet_read_expect(SSH2_MSG_KEX_ECDH_REPLY);
/* hostkey */
server_host_key_blob = packet_get_string(&sbloblen);
server_host_key = key_from_blob(server_host_key_blob, sbloblen);
if (server_host_key == NULL)
fatal("cannot decode server_host_key_blob");
if (server_host_key->type != kex->hostkey_type)
fatal("type mismatch for decoded server_host_key_blob");
if (kex->verify_host_key == NULL)
fatal("cannot verify server_host_key");
if (kex->verify_host_key(server_host_key) == -1)
fatal("server_host_key verification failed");
/* Q_S, server public key */
if ((server_public = EC_POINT_new(group)) == NULL)
fatal("%s: EC_POINT_new failed", __func__);
packet_get_ecpoint(group, server_public);
if (key_ec_validate_public(group, server_public) != 0)
fatal("%s: invalid server public key", __func__);
#ifdef DEBUG_KEXECDH
fputs("server public key:\n", stderr);
key_dump_ec_point(group, server_public);
#endif
/* signed H */
signature = packet_get_string(&slen);
packet_check_eom();
klen = (EC_GROUP_get_degree(group) + 7) / 8;
kbuf = xmalloc(klen);
if (ECDH_compute_key(kbuf, klen, server_public,
client_key, NULL) != (int)klen)
fatal("%s: ECDH_compute_key failed", __func__);
#ifdef DEBUG_KEXECDH
dump_digest("shared secret", kbuf, klen);
#endif
if ((shared_secret = BN_new()) == NULL)
fatal("%s: BN_new failed", __func__);
if (BN_bin2bn(kbuf, klen, shared_secret) == NULL)
fatal("%s: BN_bin2bn failed", __func__);
memset(kbuf, 0, klen);
xfree(kbuf);
/* calc and verify H */
kex_ecdh_hash(
kex->evp_md,
group,
kex->client_version_string,
kex->server_version_string,
buffer_ptr(&kex->my), buffer_len(&kex->my),
buffer_ptr(&kex->peer), buffer_len(&kex->peer),
server_host_key_blob, sbloblen,
EC_KEY_get0_public_key(client_key),
server_public,
shared_secret,
&hash, &hashlen
);
xfree(server_host_key_blob);
EC_POINT_clear_free(server_public);
EC_KEY_free(client_key);
if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1)
fatal("key_verify failed for server_host_key");
key_free(server_host_key);
xfree(signature);
/* save session id */
if (kex->session_id == NULL) {
kex->session_id_len = hashlen;
kex->session_id = xmalloc(kex->session_id_len);
memcpy(kex->session_id, hash, kex->session_id_len);
}
kex_derive_keys(kex, hash, hashlen, shared_secret);
BN_clear_free(shared_secret);
kex_finish(kex);
}
#else /* OPENSSL_HAS_ECC */
void
kexecdh_client(Kex *kex)
{
fatal("ECC support is not enabled");
}
#endif /* OPENSSL_HAS_ECC */

173
kexecdhs.c Normal file
View File

@ -0,0 +1,173 @@
/* $OpenBSD: kexecdhs.c,v 1.2 2010/09/22 05:01:29 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include <signal.h>
#include "xmalloc.h"
#include "buffer.h"
#include "key.h"
#include "cipher.h"
#include "kex.h"
#include "log.h"
#include "packet.h"
#include "dh.h"
#include "ssh2.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#ifdef OPENSSL_HAS_ECC
#include <openssl/ecdh.h>
void
kexecdh_server(Kex *kex)
{
EC_POINT *client_public;
EC_KEY *server_key;
const EC_GROUP *group;
BIGNUM *shared_secret;
Key *server_host_private, *server_host_public;
u_char *server_host_key_blob = NULL, *signature = NULL;
u_char *kbuf, *hash;
u_int klen, slen, sbloblen, hashlen;
int curve_nid;
if ((curve_nid = kex_ecdh_name_to_nid(kex->name)) == -1)
fatal("%s: unsupported ECDH curve \"%s\"", __func__, kex->name);
if ((server_key = EC_KEY_new_by_curve_name(curve_nid)) == NULL)
fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
if (EC_KEY_generate_key(server_key) != 1)
fatal("%s: EC_KEY_generate_key failed", __func__);
group = EC_KEY_get0_group(server_key);
#ifdef DEBUG_KEXECDH
fputs("server private key:\n", stderr);
key_dump_ec_key(server_key);
#endif
if (kex->load_host_public_key == NULL ||
kex->load_host_private_key == NULL)
fatal("Cannot load hostkey");
server_host_public = kex->load_host_public_key(kex->hostkey_type);
if (server_host_public == NULL)
fatal("Unsupported hostkey type %d", kex->hostkey_type);
server_host_private = kex->load_host_private_key(kex->hostkey_type);
if (server_host_private == NULL)
fatal("Missing private key for hostkey type %d",
kex->hostkey_type);
debug("expecting SSH2_MSG_KEX_ECDH_INIT");
packet_read_expect(SSH2_MSG_KEX_ECDH_INIT);
if ((client_public = EC_POINT_new(group)) == NULL)
fatal("%s: EC_POINT_new failed", __func__);
packet_get_ecpoint(group, client_public);
packet_check_eom();
if (key_ec_validate_public(group, client_public) != 0)
fatal("%s: invalid client public key", __func__);
#ifdef DEBUG_KEXECDH
fputs("client public key:\n", stderr);
key_dump_ec_point(group, client_public);
#endif
/* Calculate shared_secret */
klen = (EC_GROUP_get_degree(group) + 7) / 8;
kbuf = xmalloc(klen);
if (ECDH_compute_key(kbuf, klen, client_public,
server_key, NULL) != (int)klen)
fatal("%s: ECDH_compute_key failed", __func__);
#ifdef DEBUG_KEXDH
dump_digest("shared secret", kbuf, klen);
#endif
if ((shared_secret = BN_new()) == NULL)
fatal("%s: BN_new failed", __func__);
if (BN_bin2bn(kbuf, klen, shared_secret) == NULL)
fatal("%s: BN_bin2bn failed", __func__);
memset(kbuf, 0, klen);
xfree(kbuf);
/* calc H */
key_to_blob(server_host_public, &server_host_key_blob, &sbloblen);
kex_ecdh_hash(
kex->evp_md,
group,
kex->client_version_string,
kex->server_version_string,
buffer_ptr(&kex->peer), buffer_len(&kex->peer),
buffer_ptr(&kex->my), buffer_len(&kex->my),
server_host_key_blob, sbloblen,
client_public,
EC_KEY_get0_public_key(server_key),
shared_secret,
&hash, &hashlen
);
EC_POINT_clear_free(client_public);
/* save session id := H */
if (kex->session_id == NULL) {
kex->session_id_len = hashlen;
kex->session_id = xmalloc(kex->session_id_len);
memcpy(kex->session_id, hash, kex->session_id_len);
}
/* sign H */
if (PRIVSEP(key_sign(server_host_private, &signature, &slen,
hash, hashlen)) < 0)
fatal("kexdh_server: key_sign failed");
/* destroy_sensitive_data(); */
/* send server hostkey, ECDH pubkey 'Q_S' and signed H */
packet_start(SSH2_MSG_KEX_ECDH_REPLY);
packet_put_string(server_host_key_blob, sbloblen);
packet_put_ecpoint(group, EC_KEY_get0_public_key(server_key));
packet_put_string(signature, slen);
packet_send();
xfree(signature);
xfree(server_host_key_blob);
/* have keys, free server key */
EC_KEY_free(server_key);
kex_derive_keys(kex, hash, hashlen, shared_secret);
BN_clear_free(shared_secret);
kex_finish(kex);
}
#else /* OPENSSL_HAS_ECC */
void
kexecdh_server(Kex *kex)
{
fatal("ECC support is not enabled");
}
#endif /* OPENSSL_HAS_ECC */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexgexc.c,v 1.11 2006/11/06 21:25:28 markus Exp $ */
/* $OpenBSD: kexgexc.c,v 1.12 2010/11/10 01:33:07 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@ -28,6 +28,8 @@
#include <sys/types.h>
#include <openssl/dh.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexgexs.c,v 1.13 2010/02/26 20:29:54 djm Exp $ */
/* $OpenBSD: kexgexs.c,v 1.14 2010/11/10 01:33:07 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@ -33,6 +33,8 @@
#include <string.h>
#include <signal.h>
#include <openssl/dh.h>
#include "xmalloc.h"
#include "buffer.h"
#include "key.h"

673
key.c

File diff suppressed because it is too large Load Diff

33
key.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: key.h,v 1.30 2010/04/16 01:47:26 djm Exp $ */
/* $OpenBSD: key.h,v 1.33 2010/10/28 11:22:09 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -29,14 +29,19 @@
#include "buffer.h"
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#ifdef OPENSSL_HAS_ECC
#include <openssl/ec.h>
#endif
typedef struct Key Key;
enum types {
KEY_RSA1,
KEY_RSA,
KEY_DSA,
KEY_ECDSA,
KEY_RSA_CERT,
KEY_DSA_CERT,
KEY_ECDSA_CERT,
KEY_RSA_CERT_V00,
KEY_DSA_CERT_V00,
KEY_UNSPEC
@ -73,6 +78,12 @@ struct Key {
int flags;
RSA *rsa;
DSA *dsa;
int ecdsa_nid; /* NID of curve */
#ifdef OPENSSL_HAS_ECC
EC_KEY *ecdsa;
#else
void *ecdsa;
#endif
struct KeyCert *cert;
};
@ -104,9 +115,22 @@ int key_cert_check_authority(const Key *, int, int, const char *,
const char **);
int key_cert_is_legacy(Key *);
int key_ecdsa_nid_from_name(const char *);
int key_curve_name_to_nid(const char *);
const char * key_curve_nid_to_name(int);
u_int key_curve_nid_to_bits(int);
int key_ecdsa_bits_to_nid(int);
#ifdef OPENSSL_HAS_ECC
int key_ecdsa_key_to_nid(EC_KEY *);
const EVP_MD * key_ec_nid_to_evpmd(int nid);
int key_ec_validate_public(const EC_GROUP *, const EC_POINT *);
int key_ec_validate_private(const EC_KEY *);
#endif
Key *key_from_blob(const u_char *, u_int);
int key_to_blob(const Key *, u_char **, u_int *);
const char *key_ssh_name(const Key *);
const char *key_ssh_name_plain(const Key *);
int key_names_valid2(const char *);
int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
@ -114,7 +138,14 @@ int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
int ssh_ecdsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
int ssh_ecdsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
int ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
#if defined(OPENSSL_HAS_ECC) && (defined(DEBUG_KEXECDH) || defined(DEBUG_PK))
void key_dump_ec_point(const EC_GROUP *, const EC_POINT *);
void key_dump_ec_key(const EC_KEY *);
#endif
#endif

View File

@ -273,7 +273,7 @@ login_logout(struct logininfo *li)
* try to retrieve lastlog information from wtmp/wtmpx.
*/
unsigned int
login_get_lastlog_time(const int uid)
login_get_lastlog_time(const uid_t uid)
{
struct logininfo li;
@ -297,7 +297,7 @@ login_get_lastlog_time(const int uid)
* 0 on failure (will use OpenSSH's logging facilities for diagnostics)
*/
struct logininfo *
login_get_lastlog(struct logininfo *li, const int uid)
login_get_lastlog(struct logininfo *li, const uid_t uid)
{
struct passwd *pw;
@ -311,7 +311,8 @@ login_get_lastlog(struct logininfo *li, const int uid)
*/
pw = getpwuid(uid);
if (pw == NULL)
fatal("%s: Cannot find account for uid %i", __func__, uid);
fatal("%s: Cannot find account for uid %ld", __func__,
(long)uid);
/* No MIN_SIZEOF here - we absolutely *must not* truncate the
* username (XXX - so check for trunc!) */
@ -335,7 +336,7 @@ login_get_lastlog(struct logininfo *li, const int uid)
* allocation fails, the program halts.
*/
struct
logininfo *login_alloc_entry(int pid, const char *username,
logininfo *login_alloc_entry(pid_t pid, const char *username,
const char *hostname, const char *line)
{
struct logininfo *newli;
@ -363,7 +364,7 @@ login_free_entry(struct logininfo *li)
* Returns: 1
*/
int
login_init_entry(struct logininfo *li, int pid, const char *username,
login_init_entry(struct logininfo *li, pid_t pid, const char *username,
const char *hostname, const char *line)
{
struct passwd *pw;
@ -468,9 +469,9 @@ login_write(struct logininfo *li)
#endif
#ifdef SSH_AUDIT_EVENTS
if (li->type == LTYPE_LOGIN)
audit_session_open(li->line);
audit_session_open(li);
else if (li->type == LTYPE_LOGOUT)
audit_session_close(li->line);
audit_session_close(li);
#endif
return (0);
}
@ -872,11 +873,13 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut)
pos = (off_t)tty * sizeof(struct utmp);
if ((ret = lseek(fd, pos, SEEK_SET)) == -1) {
logit("%s: lseek: %s", __func__, strerror(errno));
close(fd);
return (0);
}
if (ret != pos) {
logit("%s: Couldn't seek to tty %d slot in %s",
__func__, tty, UTMP_FILE);
close(fd);
return (0);
}
/*
@ -892,16 +895,20 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut)
if ((ret = lseek(fd, pos, SEEK_SET)) == -1) {
logit("%s: lseek: %s", __func__, strerror(errno));
close(fd);
return (0);
}
if (ret != pos) {
logit("%s: Couldn't seek to tty %d slot in %s",
__func__, tty, UTMP_FILE);
close(fd);
return (0);
}
if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) {
logit("%s: error writing %s: %s", __func__,
UTMP_FILE, strerror(errno));
close(fd);
return (0);
}
close(fd);
@ -1205,7 +1212,7 @@ wtmp_get_entry(struct logininfo *li)
close (fd);
return (0);
}
if ( wtmp_islogin(li, &ut) ) {
if (wtmp_islogin(li, &ut) ) {
found = 1;
/*
* We've already checked for a time in struct
@ -1496,11 +1503,12 @@ lastlog_openseek(struct logininfo *li, int *fd, int filemode)
if (S_ISREG(st.st_mode)) {
/* find this uid's offset in the lastlog file */
offset = (off_t) ((long)li->uid * sizeof(struct lastlog));
offset = (off_t) ((u_long)li->uid * sizeof(struct lastlog));
if (lseek(*fd, offset, SEEK_SET) != offset) {
logit("%s: %s->lseek(): %s", __func__,
lastlog_file, strerror(errno));
close(*fd);
return (0);
}
}
@ -1672,7 +1680,7 @@ record_failed_login(const char *username, const char *hostname,
strerror(errno));
goto out;
}
if((fst.st_mode & (S_IRWXG | S_IRWXO)) || (fst.st_uid != 0)){
if((fst.st_mode & (S_IXGRP | S_IRWXO)) || (fst.st_uid != 0)){
logit("Excess permission or bad ownership on file %s",
_PATH_BTMP);
goto out;

View File

@ -63,8 +63,8 @@ struct logininfo {
char progname[LINFO_PROGSIZE]; /* name of program (for PAM) */
int progname_null;
short int type; /* type of login (LTYPE_*) */
int pid; /* PID of login process */
int uid; /* UID of this user */
pid_t pid; /* PID of login process */
uid_t uid; /* UID of this user */
char line[LINFO_LINESIZE]; /* tty/pty name */
char username[LINFO_NAMESIZE]; /* login username */
char hostname[LINFO_HOSTSIZE]; /* remote hostname */
@ -86,12 +86,12 @@ struct logininfo {
/** 'public' functions */
/* construct a new login entry */
struct logininfo *login_alloc_entry(int pid, const char *username,
struct logininfo *login_alloc_entry(pid_t pid, const char *username,
const char *hostname, const char *line);
/* free a structure */
void login_free_entry(struct logininfo *li);
/* fill out a pre-allocated structure with useful information */
int login_init_entry(struct logininfo *li, int pid, const char *username,
int login_init_entry(struct logininfo *li, pid_t pid, const char *username,
const char *hostname, const char *line);
/* place the current time in a logininfo struct */
void login_set_current_time(struct logininfo *li);
@ -117,9 +117,9 @@ void login_set_addr(struct logininfo *li, const struct sockaddr *sa,
* lastlog retrieval functions
*/
/* lastlog *entry* functions fill out a logininfo */
struct logininfo *login_get_lastlog(struct logininfo *li, const int uid);
struct logininfo *login_get_lastlog(struct logininfo *li, const uid_t uid);
/* lastlog *time* functions return time_t equivalent (uint) */
unsigned int login_get_lastlog_time(const int uid);
unsigned int login_get_lastlog_time(const uid_t uid);
/* produce various forms of the line filename */
char *line_fullname(char *dst, const char *src, u_int dstsize);

141
misc.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: misc.c,v 1.80 2010/07/21 02:10:58 djm Exp $ */
/* $OpenBSD: misc.c,v 1.84 2010/11/21 01:01:13 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
@ -35,9 +35,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <errno.h>
@ -850,16 +853,138 @@ ms_to_timeval(struct timeval *tv, int ms)
tv->tv_usec = (ms % 1000) * 1000;
}
int
timingsafe_bcmp(const void *b1, const void *b2, size_t n)
void
bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen)
{
const unsigned char *p1 = b1, *p2 = b2;
int ret = 0;
bw->buflen = buflen;
bw->rate = kbps;
bw->thresh = bw->rate;
bw->lamt = 0;
timerclear(&bw->bwstart);
timerclear(&bw->bwend);
}
for (; n > 0; n--)
ret |= *p1++ ^ *p2++;
return (ret != 0);
/* Callback from read/write loop to insert bandwidth-limiting delays */
void
bandwidth_limit(struct bwlimit *bw, size_t read_len)
{
u_int64_t waitlen;
struct timespec ts, rm;
if (!timerisset(&bw->bwstart)) {
gettimeofday(&bw->bwstart, NULL);
return;
}
bw->lamt += read_len;
if (bw->lamt < bw->thresh)
return;
gettimeofday(&bw->bwend, NULL);
timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
if (!timerisset(&bw->bwend))
return;
bw->lamt *= 8;
waitlen = (double)1000000L * bw->lamt / bw->rate;
bw->bwstart.tv_sec = waitlen / 1000000L;
bw->bwstart.tv_usec = waitlen % 1000000L;
if (timercmp(&bw->bwstart, &bw->bwend, >)) {
timersub(&bw->bwstart, &bw->bwend, &bw->bwend);
/* Adjust the wait time */
if (bw->bwend.tv_sec) {
bw->thresh /= 2;
if (bw->thresh < bw->buflen / 4)
bw->thresh = bw->buflen / 4;
} else if (bw->bwend.tv_usec < 10000) {
bw->thresh *= 2;
if (bw->thresh > bw->buflen * 8)
bw->thresh = bw->buflen * 8;
}
TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts);
while (nanosleep(&ts, &rm) == -1) {
if (errno != EINTR)
break;
ts = rm;
}
}
bw->lamt = 0;
gettimeofday(&bw->bwstart, NULL);
}
/* Make a template filename for mk[sd]temp() */
void
mktemp_proto(char *s, size_t len)
{
const char *tmpdir;
int r;
if ((tmpdir = getenv("TMPDIR")) != NULL) {
r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir);
if (r > 0 && (size_t)r < len)
return;
}
r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX");
if (r < 0 || (size_t)r >= len)
fatal("%s: template string too short", __func__);
}
static const struct {
const char *name;
int value;
} ipqos[] = {
{ "af11", IPTOS_DSCP_AF11 },
{ "af12", IPTOS_DSCP_AF12 },
{ "af13", IPTOS_DSCP_AF13 },
{ "af14", IPTOS_DSCP_AF21 },
{ "af22", IPTOS_DSCP_AF22 },
{ "af23", IPTOS_DSCP_AF23 },
{ "af31", IPTOS_DSCP_AF31 },
{ "af32", IPTOS_DSCP_AF32 },
{ "af33", IPTOS_DSCP_AF33 },
{ "af41", IPTOS_DSCP_AF41 },
{ "af42", IPTOS_DSCP_AF42 },
{ "af43", IPTOS_DSCP_AF43 },
{ "cs0", IPTOS_DSCP_CS0 },
{ "cs1", IPTOS_DSCP_CS1 },
{ "cs2", IPTOS_DSCP_CS2 },
{ "cs3", IPTOS_DSCP_CS3 },
{ "cs4", IPTOS_DSCP_CS4 },
{ "cs5", IPTOS_DSCP_CS5 },
{ "cs6", IPTOS_DSCP_CS6 },
{ "cs7", IPTOS_DSCP_CS7 },
{ "ef", IPTOS_DSCP_EF },
{ "lowdelay", IPTOS_LOWDELAY },
{ "throughput", IPTOS_THROUGHPUT },
{ "reliability", IPTOS_RELIABILITY },
{ NULL, -1 }
};
int
parse_ipqos(const char *cp)
{
u_int i;
char *ep;
long val;
if (cp == NULL)
return -1;
for (i = 0; ipqos[i].name != NULL; i++) {
if (strcasecmp(cp, ipqos[i].name) == 0)
return ipqos[i].value;
}
/* Try parsing as an integer */
val = strtol(cp, &ep, 0);
if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255)
return -1;
return val;
}
void
sock_set_v6only(int s)
{

14
misc.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: misc.h,v 1.43 2010/07/13 23:13:16 djm Exp $ */
/* $OpenBSD: misc.h,v 1.47 2010/11/21 01:01:13 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -36,7 +36,6 @@ void sanitise_stdfd(void);
void ms_subtract_diff(struct timeval *, int *);
void ms_to_timeval(struct timeval *, int);
void sock_set_v6only(int);
int timingsafe_bcmp(const void *, const void *, size_t);
struct passwd *pwcopy(struct passwd *);
const char *ssh_gai_strerror(int);
@ -80,6 +79,17 @@ void put_u32(void *, u_int32_t)
void put_u16(void *, u_int16_t)
__attribute__((__bounded__( __minbytes__, 1, 2)));
struct bwlimit {
size_t buflen;
u_int64_t rate, thresh, lamt;
struct timeval bwstart, bwend;
};
void bandwidth_limit_init(struct bwlimit *, u_int64_t, size_t);
void bandwidth_limit(struct bwlimit *, size_t);
int parse_ipqos(const char *);
void mktemp_proto(char *, size_t);
/* readpass.c */

View File

@ -17,7 +17,6 @@ DESCRIPTION
The file consists of newline-separated records, one per modulus,
containing seven space separated fields. These fields are as follows:
timestamp The time that the modulus was last processed as
YYYYMMDDHHMMSS.

View File

@ -1,4 +1,4 @@
/* $OpenBSD: moduli.c,v 1.21 2008/06/26 09:19:40 djm Exp $ */
/* $OpenBSD: moduli.c,v 1.22 2010/11/10 01:33:07 djm Exp $ */
/*
* Copyright 1994 Phil Karn <karn@qualcomm.com>
* Copyright 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com>
@ -54,6 +54,8 @@
#include "dh.h"
#include "log.h"
#include "openbsd-compat/openssl-compat.h"
/*
* File output defines
*/
@ -600,7 +602,7 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
* that p is also prime. A single pass will weed out the
* vast majority of composite q's.
*/
if (BN_is_prime(q, 1, NULL, ctx, NULL) <= 0) {
if (BN_is_prime_ex(q, 1, ctx, NULL) <= 0) {
debug("%10u: q failed first possible prime test",
count_in);
continue;
@ -613,14 +615,14 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
* will show up on the first Rabin-Miller iteration so it
* doesn't hurt to specify a high iteration count.
*/
if (!BN_is_prime(p, trials, NULL, ctx, NULL)) {
if (!BN_is_prime_ex(p, trials, ctx, NULL)) {
debug("%10u: p is not prime", count_in);
continue;
}
debug("%10u: p is almost certainly prime", count_in);
/* recheck q more rigorously */
if (!BN_is_prime(q, trials - 1, NULL, ctx, NULL)) {
if (!BN_is_prime_ex(q, trials - 1, ctx, NULL)) {
debug("%10u: q is not prime", count_in);
continue;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.108 2010/07/13 23:13:16 djm Exp $ */
/* $OpenBSD: monitor.c,v 1.110 2010/09/09 10:45:45 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -590,10 +590,10 @@ mm_answer_sign(int sock, Buffer *m)
p = buffer_get_string(m, &datlen);
/*
* Supported KEX types will only return SHA1 (20 byte) or
* SHA256 (32 byte) hashes
* Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),
* SHA384 (48 bytes) and SHA512 (64 bytes).
*/
if (datlen != 20 && datlen != 32)
if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64)
fatal("%s: data length incorrect: %u", __func__, datlen);
/* save session id, it will be passed on the first call */
@ -1691,6 +1691,7 @@ mm_get_kex(Buffer *m)
kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
kex->server = 1;
kex->hostkey_type = buffer_get_int(m);
kex->kex_type = buffer_get_int(m);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.c,v 1.69 2010/03/07 11:57:13 dtucker Exp $ */
/* $OpenBSD: monitor_wrap.c,v 1.70 2010/08/31 11:54:45 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -73,6 +73,7 @@
#include "misc.h"
#include "schnorr.h"
#include "jpake.h"
#include "uuencode.h"
#include "channels.h"
#include "session.h"

60
mux.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: mux.c,v 1.21 2010/06/25 23:15:36 djm Exp $ */
/* $OpenBSD: mux.c,v 1.24 2011/01/13 21:54:53 djm Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
@ -879,7 +879,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Allow forward to to %s:%u? ",
if (!ask_permission("Allow forward to %s:%u? ",
chost, cport)) {
debug2("%s: stdio fwd refused by user", __func__);
/* prepare reply */
@ -1026,6 +1026,9 @@ muxserver_listen(void)
struct sockaddr_un addr;
socklen_t sun_len;
mode_t old_umask;
char *orig_control_path = options.control_path;
char rbuf[16+1];
u_int i, r;
if (options.control_path == NULL ||
options.control_master == SSHCTL_MASTER_NO)
@ -1033,6 +1036,23 @@ muxserver_listen(void)
debug("setting up multiplex master socket");
/*
* Use a temporary path before listen so we can pseudo-atomically
* establish the listening socket in its final location to avoid
* other processes racing in between bind() and listen() and hitting
* an unready socket.
*/
for (i = 0; i < sizeof(rbuf) - 1; i++) {
r = arc4random_uniform(26+26+10);
rbuf[i] = (r < 26) ? 'a' + r :
(r < 26*2) ? 'A' + r - 26 :
'0' + r - 26 - 26;
}
rbuf[sizeof(rbuf) - 1] = '\0';
options.control_path = NULL;
xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
debug3("%s: temporary control path %s", __func__, options.control_path);
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
sun_len = offsetof(struct sockaddr_un, sun_path) +
@ -1051,6 +1071,7 @@ muxserver_listen(void)
if (errno == EINVAL || errno == EADDRINUSE) {
error("ControlSocket %s already exists, "
"disabling multiplexing", options.control_path);
disable_mux_master:
close(muxserver_sock);
muxserver_sock = -1;
xfree(options.control_path);
@ -1065,12 +1086,29 @@ muxserver_listen(void)
if (listen(muxserver_sock, 64) == -1)
fatal("%s listen(): %s", __func__, strerror(errno));
/* Now atomically "move" the mux socket into position */
if (link(options.control_path, orig_control_path) != 0) {
if (errno != EEXIST) {
fatal("%s: link mux listener %s => %s: %s", __func__,
options.control_path, orig_control_path,
strerror(errno));
}
error("ControlSocket %s already exists, disabling multiplexing",
orig_control_path);
xfree(orig_control_path);
unlink(options.control_path);
goto disable_mux_master;
}
unlink(options.control_path);
xfree(options.control_path);
options.control_path = orig_control_path;
set_nonblock(muxserver_sock);
mux_listener_channel = channel_new("mux listener",
SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, addr.sun_path, 1);
0, options.control_path, 1);
mux_listener_channel->mux_rcb = mux_master_read_cb;
debug3("%s: mux listener channel %d fd %d", __func__,
mux_listener_channel->self, mux_listener_channel->sock);
@ -1492,7 +1530,7 @@ mux_client_request_forward(int fd, u_int ftype, Forward *fwd)
case MUX_S_FAILURE:
e = buffer_get_string(&m, NULL);
buffer_free(&m);
error("%s: session request failed: %s", __func__, e);
error("%s: forwarding request failed: %s", __func__, e);
return -1;
default:
fatal("%s: unexpected response from master 0x%08x",
@ -1611,12 +1649,12 @@ mux_client_request_session(int fd)
case MUX_S_PERMISSION_DENIED:
e = buffer_get_string(&m, NULL);
buffer_free(&m);
error("Master refused forwarding request: %s", e);
error("Master refused session request: %s", e);
return -1;
case MUX_S_FAILURE:
e = buffer_get_string(&m, NULL);
buffer_free(&m);
error("%s: forwarding request failed: %s", __func__, e);
error("%s: session request failed: %s", __func__, e);
return -1;
default:
buffer_free(&m);
@ -1743,7 +1781,7 @@ mux_client_request_stdio_fwd(int fd)
case MUX_S_PERMISSION_DENIED:
e = buffer_get_string(&m, NULL);
buffer_free(&m);
fatal("Master refused forwarding request: %s", e);
fatal("Master refused stdio forwarding request: %s", e);
case MUX_S_FAILURE:
e = buffer_get_string(&m, NULL);
buffer_free(&m);
@ -1823,9 +1861,13 @@ muxclient(const char *path)
fatal("Control socket connect(%.100s): %s", path,
strerror(errno));
}
if (errno == ENOENT)
if (errno == ECONNREFUSED &&
options.control_master != SSHCTL_MASTER_NO) {
debug("Stale control socket %.100s, unlinking", path);
unlink(path);
} else if (errno == ENOENT) {
debug("Control socket \"%.100s\" does not exist", path);
else {
} else {
error("Control socket connect(%.100s): %s", path,
strerror(errno));
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: myproposal.h,v 1.25 2010/04/16 01:47:26 djm Exp $ */
/* $OpenBSD: myproposal.h,v 1.27 2010/09/01 22:42:13 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -26,26 +26,49 @@
#include <openssl/opensslv.h>
/* Old OpenSSL doesn't support what we need for DHGEX-sha256 */
#if OPENSSL_VERSION_NUMBER < 0x00907000L
# define KEX_DEFAULT_KEX \
"diffie-hellman-group-exchange-sha1," \
"diffie-hellman-group14-sha1," \
"diffie-hellman-group1-sha1"
#ifdef OPENSSL_HAS_ECC
# define KEX_ECDH_METHODS \
"ecdh-sha2-nistp256," \
"ecdh-sha2-nistp384," \
"ecdh-sha2-nistp521,"
# define HOSTKEY_ECDSA_CERT_METHODS \
"ecdsa-sha2-nistp256-cert-v01@openssh.com," \
"ecdsa-sha2-nistp384-cert-v01@openssh.com," \
"ecdsa-sha2-nistp521-cert-v01@openssh.com,"
# define HOSTKEY_ECDSA_METHODS \
"ecdsa-sha2-nistp256," \
"ecdsa-sha2-nistp384," \
"ecdsa-sha2-nistp521,"
#else
# define KEX_DEFAULT_KEX \
"diffie-hellman-group-exchange-sha256," \
"diffie-hellman-group-exchange-sha1," \
"diffie-hellman-group14-sha1," \
"diffie-hellman-group1-sha1"
# define KEX_ECDH_METHODS
# define HOSTKEY_ECDSA_CERT_METHODS
# define HOSTKEY_ECDSA_METHODS
#endif
/* Old OpenSSL doesn't support what we need for DHGEX-sha256 */
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
# define KEX_SHA256_METHODS \
"diffie-hellman-group-exchange-sha256,"
#else
# define KEX_SHA256_METHODS
#endif
# define KEX_DEFAULT_KEX \
KEX_ECDH_METHODS \
KEX_SHA256_METHODS \
"diffie-hellman-group-exchange-sha1," \
"diffie-hellman-group14-sha1," \
"diffie-hellman-group1-sha1"
#define KEX_DEFAULT_PK_ALG \
"ssh-rsa-cert-v01@openssh.com," \
"ssh-dss-cert-v01@openssh.com," \
"ssh-rsa-cert-v00@openssh.com," \
"ssh-dss-cert-v00@openssh.com," \
"ssh-rsa,ssh-dss"
HOSTKEY_ECDSA_CERT_METHODS \
"ssh-rsa-cert-v01@openssh.com," \
"ssh-dss-cert-v01@openssh.com," \
"ssh-rsa-cert-v00@openssh.com," \
"ssh-dss-cert-v00@openssh.com," \
HOSTKEY_ECDSA_METHODS \
"ssh-rsa," \
"ssh-dss"
#define KEX_DEFAULT_ENCRYPT \
"aes128-ctr,aes192-ctr,aes256-ctr," \

View File

@ -1,4 +1,4 @@
# $Id: Makefile.in,v 1.45 2010/08/16 03:15:23 dtucker Exp $
# $Id: Makefile.in,v 1.46 2010/10/07 11:19:24 djm Exp $
sysconfdir=@sysconfdir@
piddir=@piddir@
@ -16,7 +16,7 @@ RANLIB=@RANLIB@
INSTALL=@INSTALL@
LDFLAGS=-L. @LDFLAGS@
OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o vis.o
OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o timingsafe_bcmp.o vis.o
COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o

View File

@ -89,7 +89,7 @@ bindresvport_sa(int sd, struct sockaddr *sa)
port = ntohs(*portp);
if (port == 0)
port = (arc4random() % NPORTS) + STARTPORT;
port = arc4random_uniform(NPORTS) + STARTPORT;
/* Avoid warning */
error = -1;

View File

@ -240,3 +240,10 @@ strdup(const char *str)
return NULL;
}
#endif
#ifndef HAVE_ISBLANK
int isblank(int c)
{
return (c == ' ' || c == '\t');
}
#endif

View File

@ -1,4 +1,4 @@
/* $Id: bsd-misc.h,v 1.18 2005/02/25 23:07:38 dtucker Exp $ */
/* $Id: bsd-misc.h,v 1.19 2010/11/08 22:26:23 tim Exp $ */
/*
* Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org>
@ -95,4 +95,8 @@ mysig_t mysignal(int sig, mysig_t act);
#define signal(a,b) mysignal(a,b)
#ifndef HAVE_ISBLANK
int isblank(int);
#endif
#endif /* _BSD_MISC_H */

View File

@ -0,0 +1,31 @@
/*
* Public domain, 2008, Todd C. Miller <Todd.Miller@courtesan.com>
*
* $OpenBSD: charclass.h,v 1.1 2008/10/01 23:04:13 millert Exp $
*/
/* OPENBSD ORIGINAL: lib/libc/gen/charclass.h */
/*
* POSIX character class support for fnmatch() and glob().
*/
static struct cclass {
const char *name;
int (*isctype)(int);
} cclasses[] = {
{ "alnum", isalnum },
{ "alpha", isalpha },
{ "blank", isblank },
{ "cntrl", iscntrl },
{ "digit", isdigit },
{ "graph", isgraph },
{ "lower", islower },
{ "print", isprint },
{ "punct", ispunct },
{ "space", isspace },
{ "upper", isupper },
{ "xdigit", isxdigit },
{ NULL, NULL }
};
#define NCCLASSES (sizeof(cclasses) / sizeof(cclasses[0]) - 1)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: glob.c,v 1.26 2005/11/28 17:50:12 deraadt Exp $ */
/* $OpenBSD: glob.c,v 1.35 2011/01/12 01:53:14 djm Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
@ -33,36 +33,6 @@
/* OPENBSD ORIGINAL: lib/libc/gen/glob.c */
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <ctype.h>
#include <errno.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \
!defined(GLOB_HAS_GL_MATCHC) || \
!defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \
defined(BROKEN_GLOB)
static long
get_arg_max(void)
{
#ifdef ARG_MAX
return(ARG_MAX);
#elif defined(HAVE_SYSCONF) && defined(_SC_ARG_MAX)
return(sysconf(_SC_ARG_MAX));
#else
return(256); /* XXX: arbitrary */
#endif
}
/*
* glob(3) -- a superset of the one defined in POSIX 1003.2.
*
@ -88,6 +58,25 @@ get_arg_max(void)
* Number of matches in the current invocation of glob.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <ctype.h>
#include <errno.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \
!defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) || \
!defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \
defined(BROKEN_GLOB)
#include "charclass.h"
#define DOLLAR '$'
#define DOT '.'
@ -100,7 +89,6 @@ get_arg_max(void)
#define RBRACKET ']'
#define SEP '/'
#define STAR '*'
#undef TILDE /* Some platforms may already define it */
#define TILDE '~'
#define UNDERSCORE '_'
#define LBRACE '{'
@ -137,26 +125,39 @@ typedef char Char;
#define M_ONE META('?')
#define M_RNG META('-')
#define M_SET META('[')
#define M_CLASS META(':')
#define ismeta(c) (((c)&M_QUOTE) != 0)
#define GLOB_LIMIT_MALLOC 65536
#define GLOB_LIMIT_STAT 128
#define GLOB_LIMIT_READDIR 16384
struct glob_lim {
size_t glim_malloc;
size_t glim_stat;
size_t glim_readdir;
};
static int compare(const void *, const void *);
static int g_Ctoc(const Char *, char *, u_int);
static int g_lstat(Char *, struct stat *, glob_t *);
static DIR *g_opendir(Char *, glob_t *);
static Char *g_strchr(Char *, int);
static Char *g_strchr(const Char *, int);
static int g_strncmp(const Char *, const char *, size_t);
static int g_stat(Char *, struct stat *, glob_t *);
static int glob0(const Char *, glob_t *);
static int glob1(Char *, Char *, glob_t *, size_t *);
static int glob0(const Char *, glob_t *, struct glob_lim *);
static int glob1(Char *, Char *, glob_t *, struct glob_lim *);
static int glob2(Char *, Char *, Char *, Char *, Char *, Char *,
glob_t *, size_t *);
glob_t *, struct glob_lim *);
static int glob3(Char *, Char *, Char *, Char *, Char *,
Char *, Char *, glob_t *, size_t *);
static int globextend(const Char *, glob_t *, size_t *);
Char *, Char *, glob_t *, struct glob_lim *);
static int globextend(const Char *, glob_t *, struct glob_lim *,
struct stat *);
static const Char *
globtilde(const Char *, Char *, size_t, glob_t *);
static int globexp1(const Char *, glob_t *);
static int globexp2(const Char *, const Char *, glob_t *, int *);
static int globexp1(const Char *, glob_t *, struct glob_lim *);
static int globexp2(const Char *, const Char *, glob_t *,
struct glob_lim *);
static int match(Char *, Char *, Char *);
#ifdef DEBUG
static void qprintf(const char *, Char *);
@ -169,11 +170,13 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
const u_char *patnext;
int c;
Char *bufnext, *bufend, patbuf[MAXPATHLEN];
struct glob_lim limit = { 0, 0, 0 };
patnext = (u_char *) pattern;
if (!(flags & GLOB_APPEND)) {
pglob->gl_pathc = 0;
pglob->gl_pathv = NULL;
pglob->gl_statv = NULL;
if (!(flags & GLOB_DOOFFS))
pglob->gl_offs = 0;
}
@ -181,6 +184,11 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
pglob->gl_errfunc = errfunc;
pglob->gl_matchc = 0;
if (pglob->gl_offs < 0 || pglob->gl_pathc < 0 ||
pglob->gl_offs >= INT_MAX || pglob->gl_pathc >= INT_MAX ||
pglob->gl_pathc >= INT_MAX - pglob->gl_offs - 1)
return GLOB_NOSPACE;
bufnext = patbuf;
bufend = bufnext + MAXPATHLEN - 1;
if (flags & GLOB_NOESCAPE)
@ -201,9 +209,9 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
*bufnext = EOS;
if (flags & GLOB_BRACE)
return globexp1(patbuf, pglob);
return globexp1(patbuf, pglob, &limit);
else
return glob0(patbuf, pglob);
return glob0(patbuf, pglob, &limit);
}
/*
@ -212,20 +220,18 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
* characters
*/
static int
globexp1(const Char *pattern, glob_t *pglob)
globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
{
const Char* ptr = pattern;
int rv;
/* Protect a single {}, for find(1), like csh */
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
return glob0(pattern, pglob);
return glob0(pattern, pglob, limitp);
while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
if (!globexp2(ptr, pattern, pglob, &rv))
return rv;
if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
return globexp2(ptr, pattern, pglob, limitp);
return glob0(pattern, pglob);
return glob0(pattern, pglob, limitp);
}
@ -235,9 +241,10 @@ globexp1(const Char *pattern, glob_t *pglob)
* If it fails then it tries to glob the rest of the pattern and returns.
*/
static int
globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv)
globexp2(const Char *ptr, const Char *pattern, glob_t *pglob,
struct glob_lim *limitp)
{
int i;
int i, rv;
Char *lm, *ls;
const Char *pe, *pm, *pl;
Char patbuf[MAXPATHLEN];
@ -270,10 +277,8 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv)
}
/* Non matching braces; just glob the pattern */
if (i != 0 || *pe == EOS) {
*rv = glob0(patbuf, pglob);
return 0;
}
if (i != 0 || *pe == EOS)
return glob0(patbuf, pglob, limitp);
for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
switch (*pm) {
@ -319,7 +324,9 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv)
#ifdef DEBUG
qprintf("globexp2:", patbuf);
#endif
*rv = globexp1(patbuf, pglob);
rv = globexp1(patbuf, pglob, limitp);
if (rv && rv != GLOB_NOMATCH)
return rv;
/* move after the comma, to the next string */
pl = pm + 1;
@ -330,7 +337,6 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv)
break;
}
}
*rv = 0;
return 0;
}
@ -399,6 +405,47 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
return patbuf;
}
static int
g_strncmp(const Char *s1, const char *s2, size_t n)
{
int rv = 0;
while (n--) {
rv = *(Char *)s1 - *(const unsigned char *)s2++;
if (rv)
break;
if (*s1++ == '\0')
break;
}
return rv;
}
static int
g_charclass(const Char **patternp, Char **bufnextp)
{
const Char *pattern = *patternp + 1;
Char *bufnext = *bufnextp;
const Char *colon;
struct cclass *cc;
size_t len;
if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']')
return 1; /* not a character class */
len = (size_t)(colon - pattern);
for (cc = cclasses; cc->name != NULL; cc++) {
if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0')
break;
}
if (cc->name == NULL)
return -1; /* invalid character class */
*bufnext++ = M_CLASS;
*bufnext++ = (Char)(cc - &cclasses[0]);
*bufnextp = bufnext;
*patternp += len + 3;
return 0;
}
/*
* The main glob() routine: compiles the pattern (optionally processing
@ -408,12 +455,11 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
* to find no matches.
*/
static int
glob0(const Char *pattern, glob_t *pglob)
glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
{
const Char *qpatnext;
int c, err, oldpathc;
Char *bufnext, patbuf[MAXPATHLEN];
size_t limit = 0;
qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
oldpathc = pglob->gl_pathc;
@ -427,7 +473,7 @@ glob0(const Char *pattern, glob_t *pglob)
if (c == NOT)
++qpatnext;
if (*qpatnext == EOS ||
g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
g_strchr(qpatnext+1, RBRACKET) == NULL) {
*bufnext++ = LBRACKET;
if (c == NOT)
--qpatnext;
@ -438,6 +484,20 @@ glob0(const Char *pattern, glob_t *pglob)
*bufnext++ = M_NOT;
c = *qpatnext++;
do {
if (c == LBRACKET && *qpatnext == ':') {
do {
err = g_charclass(&qpatnext,
&bufnext);
if (err)
break;
c = *qpatnext++;
} while (c == LBRACKET && *qpatnext == ':');
if (err == -1 &&
!(pglob->gl_flags & GLOB_NOCHECK))
return GLOB_NOMATCH;
if (c == RBRACKET)
break;
}
*bufnext++ = CHAR(c);
if (*qpatnext == RANGE &&
(c = qpatnext[1]) != RBRACKET) {
@ -471,7 +531,7 @@ glob0(const Char *pattern, glob_t *pglob)
qprintf("glob0:", patbuf);
#endif
if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0)
if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp)) != 0)
return(err);
/*
@ -484,7 +544,7 @@ glob0(const Char *pattern, glob_t *pglob)
if ((pglob->gl_flags & GLOB_NOCHECK) ||
((pglob->gl_flags & GLOB_NOMAGIC) &&
!(pglob->gl_flags & GLOB_MAGCHAR)))
return(globextend(pattern, pglob, &limit));
return(globextend(pattern, pglob, limitp, NULL));
else
return(GLOB_NOMATCH);
}
@ -501,7 +561,7 @@ compare(const void *p, const void *q)
}
static int
glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp)
glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp)
{
Char pathbuf[MAXPATHLEN];
@ -520,7 +580,7 @@ glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp)
*/
static int
glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp)
Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp)
{
struct stat sb;
Char *p, *q;
@ -536,6 +596,14 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
if (g_lstat(pathbuf, &sb, pglob))
return(0);
if ((pglob->gl_flags & GLOB_LIMIT) &&
limitp->glim_stat++ >= GLOB_LIMIT_STAT) {
errno = 0;
*pathend++ = SEP;
*pathend = EOS;
return(GLOB_NOSPACE);
}
if (((pglob->gl_flags & GLOB_MARK) &&
pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
(S_ISLNK(sb.st_mode) &&
@ -547,7 +615,7 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
*pathend = EOS;
}
++pglob->gl_matchc;
return(globextend(pathbuf, pglob, limitp));
return(globextend(pathbuf, pglob, limitp, &sb));
}
/* Find end of next segment, copy tentatively to pathend. */
@ -581,7 +649,7 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
static int
glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob,
size_t *limitp)
struct glob_lim *limitp)
{
struct dirent *dp;
DIR *dirp;
@ -624,6 +692,14 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
u_char *sc;
Char *dc;
if ((pglob->gl_flags & GLOB_LIMIT) &&
limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) {
errno = 0;
*pathend++ = SEP;
*pathend = EOS;
return(GLOB_NOSPACE);
}
/* Initial DOT must be matched literally. */
if (dp->d_name[0] == DOT && *pattern != DOT)
continue;
@ -670,25 +746,44 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
* gl_pathv points to (gl_offs + gl_pathc + 1) items.
*/
static int
globextend(const Char *path, glob_t *pglob, size_t *limitp)
globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp,
struct stat *sb)
{
char **pathv;
int i;
u_int newsize, len;
char *copy;
ssize_t i;
size_t newn, len;
char *copy = NULL;
const Char *p;
struct stat **statv;
newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) :
malloc(newsize);
if (pathv == NULL) {
newn = 2 + pglob->gl_pathc + pglob->gl_offs;
if (pglob->gl_offs >= INT_MAX ||
pglob->gl_pathc >= INT_MAX ||
newn >= INT_MAX ||
SIZE_MAX / sizeof(*pathv) <= newn ||
SIZE_MAX / sizeof(*statv) <= newn) {
nospace:
for (i = pglob->gl_offs; i < (ssize_t)(newn - 2); i++) {
if (pglob->gl_pathv && pglob->gl_pathv[i])
free(pglob->gl_pathv[i]);
if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 &&
pglob->gl_pathv && pglob->gl_pathv[i])
free(pglob->gl_statv[i]);
}
if (pglob->gl_pathv) {
free(pglob->gl_pathv);
pglob->gl_pathv = NULL;
}
if (pglob->gl_statv) {
free(pglob->gl_statv);
pglob->gl_statv = NULL;
}
return(GLOB_NOSPACE);
}
pathv = realloc(pglob->gl_pathv, newn * sizeof(*pathv));
if (pathv == NULL)
goto nospace;
if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
/* first time around -- clear initial gl_offs items */
pathv += pglob->gl_offs;
@ -697,10 +792,39 @@ globextend(const Char *path, glob_t *pglob, size_t *limitp)
}
pglob->gl_pathv = pathv;
if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) {
statv = realloc(pglob->gl_statv, newn * sizeof(*statv));
if (statv == NULL)
goto nospace;
if (pglob->gl_statv == NULL && pglob->gl_offs > 0) {
/* first time around -- clear initial gl_offs items */
statv += pglob->gl_offs;
for (i = pglob->gl_offs; --i >= 0; )
*--statv = NULL;
}
pglob->gl_statv = statv;
if (sb == NULL)
statv[pglob->gl_offs + pglob->gl_pathc] = NULL;
else {
limitp->glim_malloc += sizeof(**statv);
if ((pglob->gl_flags & GLOB_LIMIT) &&
limitp->glim_malloc >= GLOB_LIMIT_MALLOC) {
errno = 0;
return(GLOB_NOSPACE);
}
if ((statv[pglob->gl_offs + pglob->gl_pathc] =
malloc(sizeof(**statv))) == NULL)
goto copy_error;
memcpy(statv[pglob->gl_offs + pglob->gl_pathc], sb,
sizeof(*sb));
}
statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL;
}
for (p = path; *p++;)
;
len = (size_t)(p - path);
*limitp += len;
limitp->glim_malloc += len;
if ((copy = malloc(len)) != NULL) {
if (g_Ctoc(path, copy, len)) {
free(copy);
@ -711,11 +835,12 @@ globextend(const Char *path, glob_t *pglob, size_t *limitp)
pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
if ((pglob->gl_flags & GLOB_LIMIT) &&
newsize + *limitp >= (u_int) get_arg_max()) {
(newn * sizeof(*pathv)) + limitp->glim_malloc >
GLOB_LIMIT_MALLOC) {
errno = 0;
return(GLOB_NOSPACE);
}
copy_error:
return(copy == NULL ? GLOB_NOSPACE : 0);
}
@ -751,13 +876,21 @@ match(Char *name, Char *pat, Char *patend)
return(0);
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
++pat;
while (((c = *pat++) & M_MASK) != M_END)
while (((c = *pat++) & M_MASK) != M_END) {
if ((c & M_MASK) == M_CLASS) {
Char idx = *pat & M_MASK;
if (idx < NCCLASSES &&
cclasses[idx].isctype(k))
ok = 1;
++pat;
}
if ((*pat & M_MASK) == M_RNG) {
if (c <= k && k <= pat[1])
ok = 1;
pat += 2;
} else if (c == k)
ok = 1;
}
if (ok == negate_range)
return(0);
break;
@ -785,6 +918,14 @@ globfree(glob_t *pglob)
free(pglob->gl_pathv);
pglob->gl_pathv = NULL;
}
if (pglob->gl_statv != NULL) {
for (i = 0; i < pglob->gl_pathc; i++) {
if (pglob->gl_statv[i] != NULL)
free(pglob->gl_statv[i]);
}
free(pglob->gl_statv);
pglob->gl_statv = NULL;
}
}
static DIR *
@ -830,11 +971,11 @@ g_stat(Char *fn, struct stat *sb, glob_t *pglob)
}
static Char *
g_strchr(Char *str, int ch)
g_strchr(const Char *str, int ch)
{
do {
if (*str == ch)
return (str);
return ((Char *)str);
} while (*str++);
return (NULL);
}
@ -870,5 +1011,4 @@ qprintf(const char *str, Char *s)
#endif
#endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) ||
!defined(GLOB_HAS_GL_MATCHC) */
!defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: glob.h,v 1.10 2005/12/13 00:35:22 millert Exp $ */
/* $OpenBSD: glob.h,v 1.11 2010/09/24 13:32:55 djm Exp $ */
/* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */
/*
@ -38,13 +38,15 @@
/* OPENBSD ORIGINAL: include/glob.h */
#if !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) || \
!defined(GLOB_HAS_GL_MATCHC) || \
!defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) || \
!defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \
defined(BROKEN_GLOB)
#ifndef _GLOB_H_
#define _GLOB_H_
#include <sys/stat.h>
struct stat;
typedef struct {
int gl_pathc; /* Count of total paths so far. */
@ -52,6 +54,7 @@ typedef struct {
int gl_offs; /* Reserved at beginning of gl_pathv. */
int gl_flags; /* Copy of flags parameter to glob. */
char **gl_pathv; /* List of paths matching pattern. */
struct stat **gl_statv; /* Stat entries corresponding to gl_pathv */
/* Copy of errfunc parameter to glob. */
int (*gl_errfunc)(const char *, int);
@ -75,12 +78,10 @@ typedef struct {
#define GLOB_NOSORT 0x0020 /* Don't sort. */
#define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */
/* Error values returned by glob(3) */
#define GLOB_NOSPACE (-1) /* Malloc call failed. */
#define GLOB_ABORTED (-2) /* Unignored error. */
#define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */
#define GLOB_NOSYS (-4) /* Function not supported. */
#define GLOB_ABEND GLOB_ABORTED
#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
#define GLOB_BRACE 0x0080 /* Expand braces ala csh. */
@ -89,6 +90,8 @@ typedef struct {
#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
#define GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */
#define GLOB_KEEPSTAT 0x4000 /* Retain stat data for paths in gl_statv. */
#define GLOB_ABEND GLOB_ABORTED /* backward compatibility */
int glob(const char *, int, int (*)(const char *, int), glob_t *);
void globfree(glob_t *);
@ -96,5 +99,5 @@ void globfree(glob_t *);
#endif /* !_GLOB_H_ */
#endif /* !defined(HAVE_GLOB_H) || !defined(GLOB_HAS_ALTDIRFUNC) ||
!defined(GLOB_HAS_GL_MATCHC */
!defined(GLOB_HAS_GL_MATCHC) || !defined(GLOH_HAS_GL_STATV) */

View File

@ -1,4 +1,4 @@
/* $Id: openbsd-compat.h,v 1.50 2010/08/16 03:15:23 dtucker Exp $ */
/* $Id: openbsd-compat.h,v 1.51 2010/10/07 10:25:29 djm Exp $ */
/*
* Copyright (c) 1999-2003 Damien Miller. All rights reserved.
@ -213,6 +213,10 @@ char *user_from_uid(uid_t, int);
char *group_from_gid(gid_t, int);
#endif
#ifndef HAVE_TIMINGSAFE_BCMP
int timingsafe_bcmp(const void *, const void *, size_t);
#endif
void *xmmap(size_t size);
char *xcrypt(const char *password, const char *salt);
char *shadow_pw(struct passwd *pw);

View File

@ -1,4 +1,4 @@
/* $Id: openssl-compat.c,v 1.9 2010/01/28 23:54:11 dtucker Exp $ */
/* $Id: openssl-compat.c,v 1.13 2011/01/21 22:37:06 dtucker Exp $ */
/*
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
@ -18,10 +18,20 @@
#include "includes.h"
#include <stdarg.h>
#include <string.h>
#ifdef USE_OPENSSL_ENGINE
# include <openssl/engine.h>
# include <openssl/conf.h>
#endif
#ifndef HAVE_RSA_GET_DEFAULT_METHOD
# include <openssl/rsa.h>
#endif
#include "log.h"
#define SSH_DONT_OVERLOAD_OPENSSL_FUNCS
#include "openssl-compat.h"
@ -58,6 +68,70 @@ ssh_EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt)
}
#endif
#ifndef HAVE_BN_IS_PRIME_EX
int
BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, void *cb)
{
if (cb != NULL)
fatal("%s: callback args not supported", __func__);
return BN_is_prime(p, nchecks, NULL, ctx, NULL);
}
#endif
#ifndef HAVE_RSA_GENERATE_KEY_EX
int
RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *bn_e, void *cb)
{
RSA *new_rsa, tmp_rsa;
unsigned long e;
if (cb != NULL)
fatal("%s: callback args not supported", __func__);
e = BN_get_word(bn_e);
if (e == 0xffffffffL)
fatal("%s: value of e too large", __func__);
new_rsa = RSA_generate_key(bits, e, NULL, NULL);
if (new_rsa == NULL)
return 0;
/* swap rsa/new_rsa then free new_rsa */
tmp_rsa = *rsa;
*rsa = *new_rsa;
*new_rsa = tmp_rsa;
RSA_free(new_rsa);
return 1;
}
#endif
#ifndef HAVE_DSA_GENERATE_PARAMETERS_EX
int
DSA_generate_parameters_ex(DSA *dsa, int bits, const unsigned char *seed,
int seed_len, int *counter_ret, unsigned long *h_ret, void *cb)
{
DSA *new_dsa, tmp_dsa;
if (cb != NULL)
fatal("%s: callback args not supported", __func__);
new_dsa = DSA_generate_parameters(bits, (unsigned char *)seed, seed_len,
counter_ret, h_ret, NULL, NULL);
if (new_dsa == NULL)
return 0;
/* swap dsa/new_dsa then free new_dsa */
tmp_dsa = *dsa;
*dsa = *new_dsa;
*new_dsa = tmp_dsa;
DSA_free(new_dsa);
return 1;
}
#endif
#ifndef HAVE_RSA_GET_DEFAULT_METHOD
RSA_METHOD *
RSA_get_default_method(void)
{
return RSA_PKCS1_SSLeay();
}
#endif
#ifdef USE_OPENSSL_ENGINE
void
ssh_SSLeay_add_all_algorithms(void)

View File

@ -1,4 +1,4 @@
/* $Id: openssl-compat.h,v 1.15 2010/05/12 07:50:02 djm Exp $ */
/* $Id: openssl-compat.h,v 1.18 2011/01/21 22:37:06 dtucker Exp $ */
/*
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
@ -17,6 +17,7 @@
*/
#include "includes.h"
#include <openssl/opensslv.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
@ -39,6 +40,12 @@
# define EVP_CIPHER_CTX_get_app_data(e) ((e)->app_data)
#endif
#if OPENSSL_VERSION_NUMBER < 0x1000000fL
# define LIBCRYPTO_EVP_INL_TYPE unsigned int
#else
# define LIBCRYPTO_EVP_INL_TYPE size_t
#endif
#if (OPENSSL_VERSION_NUMBER < 0x00907000L) || defined(OPENSSL_LOBOTOMISED_AES)
# define USE_BUILTIN_RIJNDAEL
#endif
@ -71,6 +78,10 @@ extern const EVP_CIPHER *evp_acss(void);
# define EVP_CIPHER_CTX_key_length(c) ((c)->key_len)
#endif
#ifndef HAVE_RSA_GET_DEFAULT_METHOD
RSA_METHOD *RSA_get_default_method(void);
#endif
/*
* We overload some of the OpenSSL crypto functions with ssh_* equivalents
* which cater for older and/or less featureful OpenSSL version.
@ -101,6 +112,19 @@ extern const EVP_CIPHER *evp_acss(void);
# define SSLeay_add_all_algorithms() ssh_SSLeay_add_all_algorithms()
# endif
# ifndef HAVE_BN_IS_PRIME_EX
int BN_is_prime_ex(const BIGNUM *, int, BN_CTX *, void *);
# endif
# ifndef HAVE_DSA_GENERATE_PARAMETERS_EX
int DSA_generate_parameters_ex(DSA *, int, const unsigned char *, int, int *,
unsigned long *, void *);
# endif
# ifndef HAVE_RSA_GENERATE_KEY_EX
int RSA_generate_key_ex(RSA *, int, BIGNUM *, void *);
# endif
int ssh_EVP_CipherInit(EVP_CIPHER_CTX *, const EVP_CIPHER *, unsigned char *,
unsigned char *, int);
int ssh_EVP_Cipher(EVP_CIPHER_CTX *, char *, char *, int);

View File

@ -1,4 +1,4 @@
/* $Id: port-linux.c,v 1.8 2010/03/01 04:52:50 dtucker Exp $ */
/* $Id: port-linux.c,v 1.11 2011/01/17 07:50:24 dtucker Exp $ */
/*
* Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com>
@ -45,7 +45,7 @@ ssh_selinux_enabled(void)
static int enabled = -1;
if (enabled == -1) {
enabled = is_selinux_enabled();
enabled = (is_selinux_enabled() == 1);
debug("SELinux support %s", enabled ? "enabled" : "disabled");
}
@ -208,14 +208,22 @@ ssh_selinux_change_context(const char *newname)
#endif /* WITH_SELINUX */
#ifdef LINUX_OOM_ADJUST
#define OOM_ADJ_PATH "/proc/self/oom_adj"
/*
* The magic "don't kill me", as documented in eg:
* The magic "don't kill me" values, old and new, as documented in eg:
* http://lxr.linux.no/#linux+v2.6.32/Documentation/filesystems/proc.txt
* http://lxr.linux.no/#linux+v2.6.36/Documentation/filesystems/proc.txt
*/
#define OOM_ADJ_NOKILL -17
static int oom_adj_save = INT_MIN;
static char *oom_adj_path = NULL;
struct {
char *path;
int value;
} oom_adjust[] = {
{"/proc/self/oom_score_adj", -1000}, /* kernels >= 2.6.36 */
{"/proc/self/oom_adj", -17}, /* kernels <= 2.6.35 */
{NULL, 0},
};
/*
* Tell the kernel's out-of-memory killer to avoid sshd.
@ -224,23 +232,31 @@ static int oom_adj_save = INT_MIN;
void
oom_adjust_setup(void)
{
int i, value;
FILE *fp;
debug3("%s", __func__);
if ((fp = fopen(OOM_ADJ_PATH, "r+")) != NULL) {
if (fscanf(fp, "%d", &oom_adj_save) != 1)
verbose("error reading %s: %s", OOM_ADJ_PATH, strerror(errno));
else {
rewind(fp);
if (fprintf(fp, "%d\n", OOM_ADJ_NOKILL) <= 0)
verbose("error writing %s: %s",
OOM_ADJ_PATH, strerror(errno));
else
verbose("Set %s from %d to %d",
OOM_ADJ_PATH, oom_adj_save, OOM_ADJ_NOKILL);
for (i = 0; oom_adjust[i].path != NULL; i++) {
oom_adj_path = oom_adjust[i].path;
value = oom_adjust[i].value;
if ((fp = fopen(oom_adj_path, "r+")) != NULL) {
if (fscanf(fp, "%d", &oom_adj_save) != 1)
verbose("error reading %s: %s", oom_adj_path,
strerror(errno));
else {
rewind(fp);
if (fprintf(fp, "%d\n", value) <= 0)
verbose("error writing %s: %s",
oom_adj_path, strerror(errno));
else
verbose("Set %s from %d to %d",
oom_adj_path, oom_adj_save, value);
}
fclose(fp);
return;
}
fclose(fp);
}
oom_adj_path = NULL;
}
/* Restore the saved OOM adjustment */
@ -250,13 +266,14 @@ oom_adjust_restore(void)
FILE *fp;
debug3("%s", __func__);
if (oom_adj_save == INT_MIN || (fp = fopen(OOM_ADJ_PATH, "w")) == NULL)
if (oom_adj_save == INT_MIN || oom_adj_path == NULL ||
(fp = fopen(oom_adj_path, "w")) == NULL)
return;
if (fprintf(fp, "%d\n", oom_adj_save) <= 0)
verbose("error writing %s: %s", OOM_ADJ_PATH, strerror(errno));
verbose("error writing %s: %s", oom_adj_path, strerror(errno));
else
verbose("Set %s to %d", OOM_ADJ_PATH, oom_adj_save);
verbose("Set %s to %d", oom_adj_path, oom_adj_save);
fclose(fp);
return;

View File

@ -1,4 +1,4 @@
/* $Id: port-solaris.c,v 1.3 2006/10/31 23:28:49 dtucker Exp $ */
/* $Id: port-solaris.c,v 1.4 2010/11/05 01:03:05 dtucker Exp $ */
/*
* Copyright (c) 2006 Chad Mynhier.
@ -197,3 +197,33 @@ solaris_contract_post_fork_parent(pid_t pid)
close(ctl_fd);
}
#endif
#ifdef USE_SOLARIS_PROJECTS
#include <sys/task.h>
#include <project.h>
/*
* Get/set solaris default project.
* If we fail, just run along gracefully.
*/
void
solaris_set_default_project(struct passwd *pw)
{
struct project *defaultproject;
struct project tempproject;
char buf[1024];
/* get default project, if we fail just return gracefully */
if ((defaultproject = getdefaultproj(pw->pw_name, &tempproject, &buf,
sizeof(buf))) > 0) {
/* set default project */
if (setproject(defaultproject->pj_name, pw->pw_name,
TASK_NORMAL) != 0)
debug("setproject(%s): %s", defaultproject->pj_name,
strerror(errno));
} else {
/* debug on getdefaultproj() error */
debug("getdefaultproj(%s): %s", pw->pw_name, strerror(errno));
}
}
#endif /* USE_SOLARIS_PROJECTS */

View File

@ -1,4 +1,4 @@
/* $Id: port-solaris.h,v 1.1 2006/08/30 17:24:42 djm Exp $ */
/* $Id: port-solaris.h,v 1.2 2010/11/05 01:03:05 dtucker Exp $ */
/*
* Copyright (c) 2006 Chad Mynhier.
@ -20,8 +20,11 @@
#include <sys/types.h>
#include <pwd.h>
void solaris_contract_pre_fork(void);
void solaris_contract_post_fork_child(void);
void solaris_contract_post_fork_parent(pid_t pid);
void solaris_set_default_project(struct passwd *);
#endif

View File

@ -0,0 +1,34 @@
/* $OpenBSD: timingsafe_bcmp.c,v 1.1 2010/09/24 13:33:00 matthew Exp $ */
/*
* Copyright (c) 2010 Damien Miller. 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.
*
* 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/string/timingsafe_bcmp.c */
#include "includes.h"
#ifndef HAVE_TIMINGSAFE_BCMP
int
timingsafe_bcmp(const void *b1, const void *b2, size_t n)
{
const unsigned char *p1 = b1, *p2 = b2;
int ret = 0;
for (; n > 0; n--)
ret |= *p1++ ^ *p2++;
return (ret != 0);
}
#endif /* TIMINGSAFE_BCMP */

View File

@ -20,6 +20,7 @@ SSH_KEYGEN=$prefix/bin/ssh-keygen
HOST_KEY_RSA1=$sysconfdir/ssh_host_key
HOST_KEY_DSA=$sysconfdir/ssh_host_dsa_key
HOST_KEY_RSA=$sysconfdir/ssh_host_rsa_key
@COMMENT_OUT_ECC@HOST_KEY_ECDSA=$sysconfdir/ssh_host_ecdsa_key
checkkeys() {
@ -32,6 +33,9 @@ checkkeys() {
if [ ! -f $HOST_KEY_RSA ]; then
${SSH_KEYGEN} -t rsa -f ${HOST_KEY_RSA} -N ""
fi
@COMMENT_OUT_ECC@ if [ ! -f $HOST_KEY_ECDSA ]; then
@COMMENT_OUT_ECC@ ${SSH_KEYGEN} -t ecdsa -f ${HOST_KEY_ECDSA} -N ""
@COMMENT_OUT_ECC@ fi
}
stop_service() {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.168 2010/07/13 23:13:16 djm Exp $ */
/* $OpenBSD: packet.c,v 1.172 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -199,13 +199,13 @@ static struct session_state *active_state, *backup_state;
static struct session_state *
alloc_session_state(void)
{
struct session_state *s = xcalloc(1, sizeof(*s));
struct session_state *s = xcalloc(1, sizeof(*s));
s->connection_in = -1;
s->connection_out = -1;
s->max_packet_size = 32768;
s->packet_timeout_ms = -1;
return s;
s->connection_in = -1;
s->connection_out = -1;
s->max_packet_size = 32768;
s->packet_timeout_ms = -1;
return s;
}
/*
@ -391,8 +391,8 @@ packet_get_ssh1_cipher(void)
}
void
packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets,
u_int64_t *bytes)
packet_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks,
u_int32_t *packets, u_int64_t *bytes)
{
struct packet_state *state;
@ -547,8 +547,7 @@ packet_start_compression(int level)
*/
void
packet_set_encryption_key(const u_char *key, u_int keylen,
int number)
packet_set_encryption_key(const u_char *key, u_int keylen, int number)
{
Cipher *cipher = cipher_by_number(number);
@ -641,6 +640,14 @@ packet_put_bignum2(BIGNUM * value)
buffer_put_bignum2(&active_state->outgoing_packet, value);
}
#ifdef OPENSSL_HAS_ECC
void
packet_put_ecpoint(const EC_GROUP *curve, const EC_POINT *point)
{
buffer_put_ecpoint(&active_state->outgoing_packet, curve, point);
}
#endif
/*
* Finalizes and sends the packet. If the encryption key has been set,
* encrypts the packet before sending.
@ -1511,6 +1518,14 @@ packet_get_bignum2(BIGNUM * value)
buffer_get_bignum2(&active_state->incoming_packet, value);
}
#ifdef OPENSSL_HAS_ECC
void
packet_get_ecpoint(const EC_GROUP *curve, EC_POINT *point)
{
buffer_get_ecpoint(&active_state->incoming_packet, curve, point);
}
#endif
void *
packet_get_raw(u_int *length_ptr)
{
@ -1546,6 +1561,13 @@ packet_get_string_ptr(u_int *length_ptr)
return buffer_get_string_ptr(&active_state->incoming_packet, length_ptr);
}
/* Ensures the returned string has no embedded \0 characters in it. */
char *
packet_get_cstring(u_int *length_ptr)
{
return buffer_get_cstring(&active_state->incoming_packet, length_ptr);
}
/*
* Sends a diagnostic message from the server to the client. This message
* can be sent at any time (but not while constructing another message). The
@ -1728,14 +1750,13 @@ packet_not_very_much_data_to_write(void)
}
static void
packet_set_tos(int interactive)
packet_set_tos(int tos)
{
#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT;
if (!packet_connection_is_on_socket() ||
!packet_connection_is_ipv4())
return;
debug3("%s: set IP_TOS 0x%02x", __func__, tos);
if (setsockopt(active_state->connection_in, IPPROTO_IP, IP_TOS, &tos,
sizeof(tos)) < 0)
error("setsockopt IP_TOS %d: %.100s:",
@ -1746,7 +1767,7 @@ packet_set_tos(int interactive)
/* Informs that the current session is interactive. Sets IP flags for that. */
void
packet_set_interactive(int interactive)
packet_set_interactive(int interactive, int qos_interactive, int qos_bulk)
{
if (active_state->set_interactive_called)
return;
@ -1759,7 +1780,7 @@ packet_set_interactive(int interactive)
if (!packet_connection_is_on_socket())
return;
set_nodelay(active_state->connection_in);
packet_set_tos(interactive);
packet_set_tos(interactive ? qos_interactive : qos_bulk);
}
/* Returns true if the current connection is interactive. */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.h,v 1.52 2009/06/27 09:29:06 andreas Exp $ */
/* $OpenBSD: packet.h,v 1.55 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -19,6 +19,9 @@
#include <termios.h>
#include <openssl/bn.h>
#ifdef OPENSSL_HAS_ECC
#include <openssl/ec.h>
#endif
void packet_set_connection(int, int);
void packet_set_timeout(int, int);
@ -31,7 +34,7 @@ u_int packet_get_encryption_key(u_char *);
void packet_set_protocol_flags(u_int);
u_int packet_get_protocol_flags(void);
void packet_start_compression(int);
void packet_set_interactive(int);
void packet_set_interactive(int, int, int);
int packet_is_interactive(void);
void packet_set_server(void);
void packet_set_authenticated(void);
@ -42,6 +45,9 @@ void packet_put_int(u_int value);
void packet_put_int64(u_int64_t value);
void packet_put_bignum(BIGNUM * value);
void packet_put_bignum2(BIGNUM * value);
#ifdef OPENSSL_HAS_ECC
void packet_put_ecpoint(const EC_GROUP *, const EC_POINT *);
#endif
void packet_put_string(const void *buf, u_int len);
void packet_put_cstring(const char *str);
void packet_put_raw(const void *buf, u_int len);
@ -59,8 +65,12 @@ u_int packet_get_int(void);
u_int64_t packet_get_int64(void);
void packet_get_bignum(BIGNUM * value);
void packet_get_bignum2(BIGNUM * value);
#ifdef OPENSSL_HAS_ECC
void packet_get_ecpoint(const EC_GROUP *, EC_POINT *);
#endif
void *packet_get_raw(u_int *length_ptr);
void *packet_get_string(u_int *length_ptr);
char *packet_get_cstring(u_int *length_ptr);
void *packet_get_string_ptr(u_int *length_ptr);
void packet_disconnect(const char *fmt,...) __attribute__((format(printf, 1, 2)));
void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));

View File

@ -1,4 +1,4 @@
/* $OpenBSD: pathnames.h,v 1.19 2010/02/11 20:37:47 djm Exp $ */
/* $OpenBSD: pathnames.h,v 1.20 2010/08/31 11:54:45 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -38,6 +38,7 @@
#define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config"
#define _PATH_HOST_KEY_FILE SSHDIR "/ssh_host_key"
#define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key"
#define _PATH_HOST_ECDSA_KEY_FILE SSHDIR "/ssh_host_ecdsa_key"
#define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key"
#define _PATH_DH_MODULI SSHDIR "/moduli"
/* Backwards compatibility */
@ -74,6 +75,7 @@
*/
#define _PATH_SSH_CLIENT_IDENTITY ".ssh/identity"
#define _PATH_SSH_CLIENT_ID_DSA ".ssh/id_dsa"
#define _PATH_SSH_CLIENT_ID_ECDSA ".ssh/id_ecdsa"
#define _PATH_SSH_CLIENT_ID_RSA ".ssh/id_rsa"
/*

View File

@ -1,4 +1,4 @@
/* $Id: platform.c,v 1.3 2009/12/20 23:49:22 dtucker Exp $ */
/* $Id: platform.c,v 1.18 2011/01/11 06:02:25 djm Exp $ */
/*
* Copyright (c) 2006 Darren Tucker. All rights reserved.
@ -16,11 +16,27 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.h"
#include "includes.h"
#include <sys/types.h>
#include <stdarg.h>
#include <unistd.h>
#include "log.h"
#include "buffer.h"
#include "servconf.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-pam.h"
#include "platform.h"
#include "openbsd-compat/openbsd-compat.h"
extern int use_privsep;
extern ServerOptions options;
void
platform_pre_listen(void)
{
@ -57,6 +73,118 @@ platform_post_fork_child(void)
#endif
}
/* return 1 if we are running with privilege to swap UIDs, 0 otherwise */
int
platform_privileged_uidswap(void)
{
#ifdef HAVE_CYGWIN
/* uid 0 is not special on Cygwin so always try */
return 1;
#else
return (getuid() == 0 || geteuid() == 0);
#endif
}
/*
* This gets called before switching UIDs, and is called even when sshd is
* not running as root.
*/
void
platform_setusercontext(struct passwd *pw)
{
#ifdef WITH_SELINUX
/* Cache selinux status for later use */
(void)ssh_selinux_enabled();
#endif
#ifdef USE_SOLARIS_PROJECTS
/* if solaris projects were detected, set the default now */
if (getuid() == 0 || geteuid() == 0)
solaris_set_default_project(pw);
#endif
#if defined(HAVE_LOGIN_CAP) && defined (__bsdi__)
if (getuid() == 0 || geteuid() == 0)
setpgid(0, 0);
# endif
#if defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
/*
* If we have both LOGIN_CAP and PAM, we want to establish creds
* before calling setusercontext (in session.c:do_setusercontext).
*/
if (getuid() == 0 || geteuid() == 0) {
if (options.use_pam) {
do_pam_setcred(use_privsep);
}
}
# endif /* USE_PAM */
#if !defined(HAVE_LOGIN_CAP) && defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
if (getuid() == 0 || geteuid() == 0) {
/* Sets login uid for accounting */
if (getluid() == -1 && setluid(pw->pw_uid) == -1)
error("setluid: %s", strerror(errno));
}
#endif
}
/*
* This gets called after we've established the user's groups, and is only
* called if sshd is running as root.
*/
void
platform_setusercontext_post_groups(struct passwd *pw)
{
#if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
/*
* PAM credentials may take the form of supplementary groups.
* These will have been wiped by the above initgroups() call.
* Reestablish them here.
*/
if (options.use_pam) {
do_pam_setcred(use_privsep);
}
#endif /* USE_PAM */
#if !defined(HAVE_LOGIN_CAP) && (defined(WITH_IRIX_PROJECT) || \
defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY))
irix_setusercontext(pw);
#endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */
#ifdef _AIX
aix_usrinfo(pw);
#endif /* _AIX */
#if !defined(HAVE_LOGIN_CAP) && defined(USE_LIBIAF)
if (set_id(pw->pw_name) != 0) {
exit(1);
}
# endif /* USE_LIBIAF */
#ifdef HAVE_SETPCRED
/*
* If we have a chroot directory, we set all creds except real
* uid which we will need for chroot. If we don't have a
* chroot directory, we don't override anything.
*/
{
char **creds = NULL, *chroot_creds[] =
{ "REAL_USER=root", NULL };
if (options.chroot_directory != NULL &&
strcasecmp(options.chroot_directory, "none") != 0)
creds = chroot_creds;
if (setpcred(pw->pw_name, creds) == -1)
fatal("Failed to set process credentials");
}
#endif /* HAVE_SETPCRED */
#ifdef WITH_SELINUX
ssh_selinux_setup_exec_context(pw->pw_name);
#endif
}
char *
platform_krb5_get_principal_name(const char *pw_name)
{

View File

@ -1,4 +1,4 @@
/* $Id: platform.h,v 1.4 2010/01/14 01:44:16 djm Exp $ */
/* $Id: platform.h,v 1.7 2010/11/05 03:47:01 dtucker Exp $ */
/*
* Copyright (c) 2006 Darren Tucker. All rights reserved.
@ -18,10 +18,15 @@
#include <sys/types.h>
#include <pwd.h>
void platform_pre_listen(void);
void platform_pre_fork(void);
void platform_post_fork_parent(pid_t child_pid);
void platform_post_fork_child(void);
int platform_privileged_uidswap(void);
void platform_setusercontext(struct passwd *);
void platform_setusercontext_post_groups(struct passwd *);
char *platform_get_krb5_client(const char *);
char *platform_krb5_get_principal_name(const char *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.c,v 1.187 2010/07/19 09:15:12 djm Exp $ */
/* $OpenBSD: readconf.c,v 1.190 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -19,6 +19,8 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <ctype.h>
#include <errno.h>
@ -132,6 +134,7 @@ typedef enum {
oHashKnownHosts,
oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
oKexAlgorithms, oIPQoS,
oDeprecated, oUnsupported
} OpCodes;
@ -240,6 +243,8 @@ static struct {
#else
{ "zeroknowledgepasswordauthentication", oUnsupported },
#endif
{ "kexalgorithms", oKexAlgorithms },
{ "ipqos", oIPQoS },
{ NULL, oBadOption }
};
@ -699,6 +704,18 @@ process_config_line(Options *options, const char *host,
options->macs = xstrdup(arg);
break;
case oKexAlgorithms:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if (!kex_names_valid(arg))
fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->kex_algorithms == NULL)
options->kex_algorithms = xstrdup(arg);
break;
case oHostKeyAlgorithms:
arg = strdelim(&s);
if (!arg || *arg == '\0')
@ -959,6 +976,23 @@ process_config_line(Options *options, const char *host,
intptr = &options->visual_host_key;
goto parse_flag;
case oIPQoS:
arg = strdelim(&s);
if ((value = parse_ipqos(arg)) == -1)
fatal("%s line %d: Bad IPQoS value: %s",
filename, linenum, arg);
arg = strdelim(&s);
if (arg == NULL)
value2 = value;
else if ((value2 = parse_ipqos(arg)) == -1)
fatal("%s line %d: Bad IPQoS value: %s",
filename, linenum, arg);
if (*activep) {
options->ip_qos_interactive = value;
options->ip_qos_bulk = value2;
}
break;
case oUseRoaming:
intptr = &options->use_roaming;
goto parse_flag;
@ -1078,6 +1112,7 @@ initialize_options(Options * options)
options->cipher = -1;
options->ciphers = NULL;
options->macs = NULL;
options->kex_algorithms = NULL;
options->hostkeyalgorithms = NULL;
options->protocol = SSH_PROTO_UNKNOWN;
options->num_identity_files = 0;
@ -1120,6 +1155,8 @@ initialize_options(Options * options)
options->use_roaming = -1;
options->visual_host_key = -1;
options->zero_knowledge_password_authentication = -1;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
}
/*
@ -1191,6 +1228,7 @@ fill_default_options(Options * options)
options->cipher = SSH_CIPHER_NOT_SET;
/* options->ciphers, default set in myproposals.h */
/* options->macs, default set in myproposals.h */
/* options->kex_algorithms, default set in myproposals.h */
/* options->hostkeyalgorithms, default set in myproposals.h */
if (options->protocol == SSH_PROTO_UNKNOWN)
options->protocol = SSH_PROTO_2;
@ -1214,6 +1252,13 @@ fill_default_options(Options * options)
xmalloc(len);
snprintf(options->identity_files[options->num_identity_files++],
len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
#ifdef OPENSSL_HAS_ECC
len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1;
options->identity_files[options->num_identity_files] =
xmalloc(len);
snprintf(options->identity_files[options->num_identity_files++],
len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA);
#endif
}
}
if (options->escape_char == -1)
@ -1266,6 +1311,10 @@ fill_default_options(Options * options)
options->visual_host_key = 0;
if (options->zero_knowledge_password_authentication == -1)
options->zero_knowledge_password_authentication = 0;
if (options->ip_qos_interactive == -1)
options->ip_qos_interactive = IPTOS_LOWDELAY;
if (options->ip_qos_bulk == -1)
options->ip_qos_bulk = IPTOS_THROUGHPUT;
/* options->local_command should not be set by default */
/* options->proxy_command should not be set by default */
/* options->user will be set in the main program if appropriate */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.h,v 1.86 2010/07/19 09:15:12 djm Exp $ */
/* $OpenBSD: readconf.h,v 1.88 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -59,6 +59,8 @@ typedef struct {
int compression_level; /* Compression level 1 (fast) to 9
* (best). */
int tcp_keep_alive; /* Set SO_KEEPALIVE. */
int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */
int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */
LogLevel log_level; /* Level for logging. */
int port; /* Port to connect. */
@ -73,6 +75,7 @@ typedef struct {
char *ciphers; /* SSH2 ciphers in order of preference. */
char *macs; /* SSH2 macs in order of preference. */
char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
int protocol; /* Protocol in order of preference. */
char *hostname; /* Real host to connect. */
char *host_key_alias; /* hostname alias for .ssh/known_hosts */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readpass.c,v 1.47 2006/08/03 03:34:42 deraadt Exp $ */
/* $OpenBSD: readpass.c,v 1.48 2010/12/15 00:49:27 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@ -33,6 +33,7 @@
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@ -49,11 +50,12 @@
static char *
ssh_askpass(char *askpass, const char *msg)
{
pid_t pid;
pid_t pid, ret;
size_t len;
char *pass;
int p[2], status, ret;
int p[2], status;
char buf[1024];
void (*osigchld)(int);
if (fflush(stdout) != 0)
error("ssh_askpass: fflush: %s", strerror(errno));
@ -63,8 +65,10 @@ ssh_askpass(char *askpass, const char *msg)
error("ssh_askpass: pipe: %s", strerror(errno));
return NULL;
}
osigchld = signal(SIGCHLD, SIG_DFL);
if ((pid = fork()) < 0) {
error("ssh_askpass: fork: %s", strerror(errno));
signal(SIGCHLD, osigchld);
return NULL;
}
if (pid == 0) {
@ -77,23 +81,24 @@ ssh_askpass(char *askpass, const char *msg)
}
close(p[1]);
len = ret = 0;
len = 0;
do {
ret = read(p[0], buf + len, sizeof(buf) - 1 - len);
if (ret == -1 && errno == EINTR)
ssize_t r = read(p[0], buf + len, sizeof(buf) - 1 - len);
if (r == -1 && errno == EINTR)
continue;
if (ret <= 0)
if (r <= 0)
break;
len += ret;
len += r;
} while (sizeof(buf) - 1 - len > 0);
buf[len] = '\0';
close(p[0]);
while (waitpid(pid, &status, 0) < 0)
while ((ret = waitpid(pid, &status, 0)) < 0)
if (errno != EINTR)
break;
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
signal(SIGCHLD, osigchld);
if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
memset(buf, 0, sizeof(buf));
return NULL;
}

View File

@ -1,6 +1,6 @@
# $OpenBSD: Makefile,v 1.54 2010/06/27 19:19:56 phessler Exp $
# $OpenBSD: Makefile,v 1.58 2011/01/06 22:46:21 djm Exp $
REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t-exec
REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t-exec
tests: $(REGRESS_TARGETS)
# Interop tests are not run by default
@ -53,14 +53,20 @@ LTESTS= connect \
localcommand \
forcecommand \
portnum \
keytype \
kextype \
cert-hostkey \
cert-userkey
cert-userkey \
host-expand
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
#INTEROP_TESTS+=ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp
#LTESTS= cipher-speed
USER!= id -un
CLEANFILES= t2.out t6.out1 t6.out2 t7.out t7.out.pub copy.1 copy.2 \
CLEANFILES= t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub copy.1 copy.2 \
t8.out t8.out.pub t9.out t9.out.pub \
authorized_keys_${USER} known_hosts pidfile \
ssh_config sshd_config.orig ssh_proxy sshd_config sshd_proxy \
rsa.pub rsa rsa1.pub rsa1 host.rsa host.rsa1 \
@ -69,45 +75,68 @@ CLEANFILES= t2.out t6.out1 t6.out2 t7.out t7.out.pub copy.1 copy.2 \
scp-ssh-wrapper.scp ssh_proxy_envpass remote_pid \
sshd_proxy_bak rsa_ssh2_cr.prv rsa_ssh2_crnl.prv \
known_hosts-cert host_ca_key* cert_host_key* \
putty.rsa2 sshd_proxy_orig \
authorized_principals_${USER}
putty.rsa2 sshd_proxy_orig ssh_proxy_bak \
key.rsa-* key.dsa-* key.ecdsa-* \
authorized_principals_${USER} expect actual
# Enable all malloc(3) randomisations and checks
TEST_ENV= "MALLOC_OPTIONS=AFGJPRX"
TEST_SSH_SSHKEYGEN?=ssh-keygen
t1:
ssh-keygen -if ${.CURDIR}/rsa_ssh2.prv | diff - ${.CURDIR}/rsa_openssh.prv
${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/rsa_ssh2.prv | diff - ${.CURDIR}/rsa_openssh.prv
tr '\n' '\r' <${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_cr.prv
${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_cr.prv | diff - ${.CURDIR}/rsa_openssh.prv
awk '{print $$0 "\r"}' ${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_crnl.prv
${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_crnl.prv | diff - ${.CURDIR}/rsa_openssh.prv
t2:
cat ${.CURDIR}/rsa_openssh.prv > $(OBJ)/t2.out
chmod 600 $(OBJ)/t2.out
ssh-keygen -yf $(OBJ)/t2.out | diff - ${.CURDIR}/rsa_openssh.pub
${TEST_SSH_SSHKEYGEN} -yf $(OBJ)/t2.out | diff - ${.CURDIR}/rsa_openssh.pub
t3:
ssh-keygen -ef ${.CURDIR}/rsa_openssh.pub >$(OBJ)/rsa_secsh.pub
ssh-keygen -if $(OBJ)/rsa_secsh.pub | diff - ${.CURDIR}/rsa_openssh.pub
rm -f ${.CURDIR}/rsa_secsh.pub
${TEST_SSH_SSHKEYGEN} -ef ${.CURDIR}/rsa_openssh.pub >$(OBJ)/t3.out
${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub
t4:
ssh-keygen -lf ${.CURDIR}/rsa_openssh.pub |\
${TEST_SSH_SSHKEYGEN} -lf ${.CURDIR}/rsa_openssh.pub |\
awk '{print $$2}' | diff - ${.CURDIR}/t4.ok
t5:
ssh-keygen -Bf ${.CURDIR}/rsa_openssh.pub |\
${TEST_SSH_SSHKEYGEN} -Bf ${.CURDIR}/rsa_openssh.pub |\
awk '{print $$2}' | diff - ${.CURDIR}/t5.ok
t6:
ssh-keygen -if ${.CURDIR}/dsa_ssh2.prv > $(OBJ)/t6.out1
ssh-keygen -if ${.CURDIR}/dsa_ssh2.pub > $(OBJ)/t6.out2
${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.prv > $(OBJ)/t6.out1
${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.pub > $(OBJ)/t6.out2
chmod 600 $(OBJ)/t6.out1
ssh-keygen -yf $(OBJ)/t6.out1 | diff - $(OBJ)/t6.out2
${TEST_SSH_SSHKEYGEN} -yf $(OBJ)/t6.out1 | diff - $(OBJ)/t6.out2
$(OBJ)/t7.out:
ssh-keygen -q -t rsa -N '' -f $@
${TEST_SSH_SSHKEYGEN} -q -t rsa -N '' -f $@
t7: $(OBJ)/t7.out
ssh-keygen -lf $(OBJ)/t7.out > /dev/null
ssh-keygen -Bf $(OBJ)/t7.out > /dev/null
${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t7.out > /dev/null
${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t7.out > /dev/null
$(OBJ)/t8.out:
${TEST_SSH_SSHKEYGEN} -q -t dsa -N '' -f $@
t8: $(OBJ)/t8.out
${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t8.out > /dev/null
${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t8.out > /dev/null
$(OBJ)/t9.out:
test "${TEST_SSH_ECC}" != yes || \
${TEST_SSH_SSHKEYGEN} -q -t ecdsa -N '' -f $@
t9: $(OBJ)/t9.out
test "${TEST_SSH_ECC}" != yes || \
${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t9.out > /dev/null
test "${TEST_SSH_ECC}" != yes || \
${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t9.out > /dev/null
t-exec: ${LTESTS:=.sh}
@if [ "x$?" = "x" ]; then exit 0; fi; \
@ -123,3 +152,5 @@ t-exec-interop: ${INTEROP_TESTS:=.sh}
(env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} sh ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \
done
# Not run by default
interop: ${INTEROP_TARGETS}

View File

@ -7,10 +7,9 @@ UNPRIV=nobody
ASOCK=${OBJ}/agent
SSH_AUTH_SOCK=/nonexistent
if grep "#undef.*HAVE_GETPEEREID" ${BUILDDIR}/config.h >/dev/null 2>&1 && \
grep "#undef.*HAVE_GETPEERUCRED" ${BUILDDIR}/config.h >/dev/null && \
grep "#undef.*HAVE_SO_PEERCRED" ${BUILDDIR}/config.h >/dev/null
then
if config_defined HAVE_GETPEEREID HAVE_GETPEERUCRED HAVE_SO_PEERCRED ; then
:
else
echo "skipped (not supported on this platform)"
exit 0
fi
@ -34,7 +33,7 @@ else
fail "ssh-add failed with $r != 1"
fi
< /dev/null ${SUDO} -S -u ${UNPRIV} ssh-add -l > /dev/null 2>&1
< /dev/null ${SUDO} -S -u ${UNPRIV} ssh-add -l 2>/dev/null
r=$?
if [ $r -lt 2 ]; then
fail "ssh-add did not fail for ${UNPRIV}: $r < 2"

View File

@ -41,7 +41,7 @@ EOF
if [ $? -ne 0 ]; then
fail "gdb failed: exit code $?"
fi
egrep 'ptrace: Operation not permitted.|procfs:.*Permission denied.|ttrace.*Permission denied.|procfs:.*: Invalid argument.' >/dev/null ${OBJ}/gdb.out
egrep 'ptrace: Operation not permitted.|procfs:.*Permission denied.|ttrace.*Permission denied.|procfs:.*: Invalid argument.|Unable to access task ' >/dev/null ${OBJ}/gdb.out
r=$?
rm -f ${OBJ}/gdb.out
if [ $r -ne 0 ]; then

View File

@ -1,8 +1,14 @@
# $OpenBSD: cert-hostkey.sh,v 1.4 2010/04/16 01:58:45 djm Exp $
# $OpenBSD: cert-hostkey.sh,v 1.5 2010/08/31 12:24:09 djm Exp $
# Placed in the Public Domain.
tid="certified host keys"
# used to disable ECC based tests on platforms without ECC
ecdsa=""
if test "x$TEST_SSH_ECC" = "xyes"; then
ecdsa=ecdsa
fi
rm -f $OBJ/known_hosts-cert $OBJ/host_ca_key* $OBJ/cert_host_key*
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
@ -18,7 +24,7 @@ ${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/host_ca_key ||\
) > $OBJ/known_hosts-cert
# Generate and sign host keys
for ktype in rsa dsa ; do
for ktype in rsa dsa $ecdsa ; do
verbose "$tid: sign host ${ktype} cert"
# Generate and sign a host key
${SSHKEYGEN} -q -N '' -t ${ktype} \
@ -28,6 +34,8 @@ for ktype in rsa dsa ; do
-I "regress host key for $USER" \
-n $HOSTS $OBJ/cert_host_key_${ktype} ||
fail "couldn't sign cert_host_key_${ktype}"
# v00 ecdsa certs do not exist
test "${ktype}" = "ecdsa" && continue
cp $OBJ/cert_host_key_${ktype} $OBJ/cert_host_key_${ktype}_v00
cp $OBJ/cert_host_key_${ktype}.pub $OBJ/cert_host_key_${ktype}_v00.pub
${SSHKEYGEN} -t v00 -h -q -s $OBJ/host_ca_key \
@ -38,7 +46,7 @@ done
# Basic connect tests
for privsep in yes no ; do
for ktype in rsa dsa rsa_v00 dsa_v00; do
for ktype in rsa dsa $ecdsa rsa_v00 dsa_v00; do
verbose "$tid: host ${ktype} cert connect privsep $privsep"
(
cat $OBJ/sshd_proxy_bak
@ -64,6 +72,11 @@ done
echon '@revoked '
echon "* "
cat $OBJ/cert_host_key_rsa.pub
if test "x$TEST_SSH_ECC" = "xyes"; then
echon '@revoked '
echon "* "
cat $OBJ/cert_host_key_ecdsa.pub
fi
echon '@revoked '
echon "* "
cat $OBJ/cert_host_key_dsa.pub
@ -75,7 +88,7 @@ done
cat $OBJ/cert_host_key_dsa_v00.pub
) > $OBJ/known_hosts-cert
for privsep in yes no ; do
for ktype in rsa dsa rsa_v00 dsa_v00; do
for ktype in rsa dsa $ecdsa rsa_v00 dsa_v00; do
verbose "$tid: host ${ktype} revoked cert privsep $privsep"
(
cat $OBJ/sshd_proxy_bak
@ -102,7 +115,7 @@ done
echon "* "
cat $OBJ/host_ca_key.pub
) > $OBJ/known_hosts-cert
for ktype in rsa dsa rsa_v00 dsa_v00 ; do
for ktype in rsa dsa $ecdsa rsa_v00 dsa_v00 ; do
verbose "$tid: host ${ktype} revoked cert"
(
cat $OBJ/sshd_proxy_bak
@ -173,7 +186,9 @@ test_one "cert has constraints" failure "-h -Oforce-command=false"
# Check downgrade of cert to raw key when no CA found
for v in v01 v00 ; do
for ktype in rsa dsa ; do
for ktype in rsa dsa $ecdsa ; do
# v00 ecdsa certs do not exist.
test "${v}${ktype}" = "v00ecdsa" && continue
rm -f $OBJ/known_hosts-cert $OBJ/cert_host_key*
verbose "$tid: host ${ktype} ${v} cert downgrade to raw key"
# Generate and sign a host key
@ -210,7 +225,9 @@ done
cat $OBJ/host_ca_key.pub
) > $OBJ/known_hosts-cert
for v in v01 v00 ; do
for kt in rsa dsa ; do
for kt in rsa dsa $ecdsa ; do
# v00 ecdsa certs do not exist.
test "${v}${ktype}" = "v00ecdsa" && continue
rm -f $OBJ/cert_host_key*
# Self-sign key
${SSHKEYGEN} -q -N '' -t ${kt} \

View File

@ -1,8 +1,14 @@
# $OpenBSD: cert-userkey.sh,v 1.6 2010/06/29 23:59:54 djm Exp $
# $OpenBSD: cert-userkey.sh,v 1.7 2010/08/31 12:24:09 djm Exp $
# Placed in the Public Domain.
tid="certified user keys"
# used to disable ECC based tests on platforms without ECC
ecdsa=""
if test "x$TEST_SSH_ECC" = "xyes"; then
ecdsa=ecdsa
fi
rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
@ -11,7 +17,7 @@ ${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/user_ca_key ||\
fail "ssh-keygen of user_ca_key failed"
# Generate and sign user keys
for ktype in rsa dsa ; do
for ktype in rsa dsa $ecdsa ; do
verbose "$tid: sign user ${ktype} cert"
${SSHKEYGEN} -q -N '' -t ${ktype} \
-f $OBJ/cert_user_key_${ktype} || \
@ -20,6 +26,8 @@ for ktype in rsa dsa ; do
"regress user key for $USER" \
-n ${USER},mekmitasdigoat $OBJ/cert_user_key_${ktype} ||
fail "couldn't sign cert_user_key_${ktype}"
# v00 ecdsa certs do not exist
test "{ktype}" = "ecdsa" && continue
cp $OBJ/cert_user_key_${ktype} $OBJ/cert_user_key_${ktype}_v00
cp $OBJ/cert_user_key_${ktype}.pub $OBJ/cert_user_key_${ktype}_v00.pub
${SSHKEYGEN} -q -t v00 -s $OBJ/user_ca_key -I \
@ -29,7 +37,7 @@ for ktype in rsa dsa ; do
done
# Test explicitly-specified principals
for ktype in rsa dsa rsa_v00 dsa_v00 ; do
for ktype in rsa dsa $ecdsa rsa_v00 dsa_v00 ; do
for privsep in yes no ; do
_prefix="${ktype} privsep $privsep"
@ -155,7 +163,7 @@ basic_tests() {
extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub"
fi
for ktype in rsa dsa rsa_v00 dsa_v00 ; do
for ktype in rsa dsa $ecdsa rsa_v00 dsa_v00 ; do
for privsep in yes no ; do
_prefix="${ktype} privsep $privsep $auth"
# Simple connect
@ -230,6 +238,11 @@ test_one() {
for auth in $auth_choice ; do
for ktype in rsa rsa_v00 ; do
case $ktype in
*_v00) keyv="-t v00" ;;
*) keyv="" ;;
esac
cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
if test "x$auth" = "xauthorized_keys" ; then
# Add CA to authorized_keys
@ -249,7 +262,7 @@ test_one() {
verbose "$tid: $ident auth $auth expect $result $ktype"
${SSHKEYGEN} -q -s $OBJ/user_ca_key \
-I "regress user key for $USER" \
$sign_opts \
$sign_opts $keyv \
$OBJ/cert_user_key_${ktype} ||
fail "couldn't sign cert_user_key_${ktype}"
@ -302,7 +315,7 @@ test_one "principals key option no principals" failure "" \
# Wrong certificate
cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
for ktype in rsa dsa rsa_v00 dsa_v00 ; do
for ktype in rsa dsa $ecdsa rsa_v00 dsa_v00 ; do
case $ktype in
*_v00) args="-t v00" ;;
*) args="" ;;

18
regress/host-expand.sh Executable file
View File

@ -0,0 +1,18 @@
# Placed in the Public Domain.
tid="expand %h and %n"
echo 'PermitLocalCommand yes' >> $OBJ/ssh_proxy
printf 'LocalCommand printf "%%%%s\\n" "%%n" "%%h"\n' >> $OBJ/ssh_proxy
cat >$OBJ/expect <<EOE
somehost
127.0.0.1
EOE
for p in 1 2; do
verbose "test $tid: proto $p"
${SSH} -F $OBJ/ssh_proxy -$p somehost true >$OBJ/actual
diff $OBJ/expect $OBJ/actual || fail "$tid proto $p"
done

30
regress/kextype.sh Executable file
View File

@ -0,0 +1,30 @@
# $OpenBSD: kextype.sh,v 1.1 2010/09/22 12:26:05 djm Exp $
# Placed in the Public Domain.
tid="login with different key exchange algorithms"
TIME=/usr/bin/time
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
if test "$TEST_SSH_ECC" = "yes"; then
kextypes="ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521"
fi
if test "$TEST_SSH_SHA256" = "yes"; then
kextypes="$kextypes diffie-hellman-group-exchange-sha256"
fi
kextypes="$kextypes diffie-hellman-group-exchange-sha1"
kextypes="$kextypes diffie-hellman-group14-sha1"
kextypes="$kextypes diffie-hellman-group1-sha1"
tries="1 2 3 4"
for k in $kextypes; do
verbose "kex $k"
for i in $tries; do
${SSH} -F $OBJ/ssh_proxy -o KexAlgorithms=$k x true
if [ $? -ne 0 ]; then
fail "ssh kex $k"
fi
done
done

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