Upgrade to OpenSSH 5.8p2.

This commit is contained in:
des 2011-05-04 07:34:44 +00:00
commit ee2afa8165
129 changed files with 5781 additions and 4267 deletions

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

@ -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
A client may request the master to establish a port forward:
Note: currently unimplemented (server will always reply with MUX_S_FAILURE).
uint32 MUX_C_OPEN_FORWARD
A client may request the master to close a port 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.4 2011/01/31 21:42:15 djm Exp $

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.8p2 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.4.2 2011/05/03 00:04:21 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 */
}

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

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,

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.
*
@ -380,16 +380,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) &&
@ -402,16 +401,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;
}
@ -519,7 +525,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;
}

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.
*
@ -184,7 +184,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)
@ -230,9 +230,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
crypto/openssh/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

@ -1,6 +1,9 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address
*/
/* #undef AIX_GETNAMEINFO_HACK */
@ -81,9 +84,6 @@
/* Define if you want to specify the path to your lastlog file */
/* #undef CONF_LASTLOG_FILE */
/* Define if you want to specify the path to your utmpx file */
/* #undef CONF_UTMPX_FILE */
/* Define if you want to specify the path to your utmp file */
/* #undef CONF_UTMP_FILE */
@ -129,6 +129,9 @@
/* Builtin PRNG command timeout */
#define ENTROPY_TIMEOUT_MSEC 200
/* File names may not contain backslash characters */
/* #undef FILESYSTEM_NO_BACKSLASH */
/* fsid_t has member val */
/* #undef FSID_HAS_VAL */
@ -147,6 +150,9 @@
/* Define if your system glob() function has gl_matchc options in glob_t */
#define GLOB_HAS_GL_MATCHC 1
/* 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 */
@ -207,6 +213,9 @@
/* Define to 1 if you have the `bindresvport_sa' function. */
#define HAVE_BINDRESVPORT_SA 1
/* Define to 1 if you have the `BN_is_prime_ex' function. */
#define HAVE_BN_IS_PRIME_EX 1
/* Define to 1 if you have the <bsm/audit.h> header file. */
/* #undef HAVE_BSM_AUDIT_H */
@ -315,6 +324,9 @@
/* Define to 1 if you have the `dirname' function. */
#define HAVE_DIRNAME 1
/* Define to 1 if you have the `DSA_generate_parameters_ex' function. */
#define HAVE_DSA_GENERATE_PARAMETERS_EX 1
/* Define to 1 if you have the <endian.h> header file. */
/* #undef HAVE_ENDIAN_H */
@ -537,9 +549,15 @@
/* Define to 1 if the system has the type `in_port_t'. */
#define HAVE_IN_PORT_T 1
/* Define if you have isblank(3C). */
#define HAVE_ISBLANK 1
/* 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 */
@ -742,6 +760,12 @@
/* Define to 1 if you have the `rresvport_af' function. */
#define HAVE_RRESVPORT_AF 1
/* Define to 1 if you have the `RSA_generate_key_ex' function. */
#define HAVE_RSA_GENERATE_KEY_EX 1
/* Define to 1 if you have the `RSA_get_default_method' function. */
#define HAVE_RSA_GET_DEFAULT_METHOD 1
/* define if you have sa_family_t data type */
#define HAVE_SA_FAMILY_T 1
@ -928,13 +952,13 @@
/* define if you have struct sockaddr_in6 data type */
#define HAVE_STRUCT_SOCKADDR_IN6 1
/* Define to 1 if `sin6_scope_id' is member of `struct sockaddr_in6'. */
/* Define to 1 if `sin6_scope_id' is a member of `struct sockaddr_in6'. */
#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1
/* define if you have struct sockaddr_storage data type */
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
/* Define to 1 if `st_blksize' is member of `struct stat'. */
/* Define to 1 if `st_blksize' is a member of `struct stat'. */
#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
/* Define to 1 if the system has the type `struct timespec'. */
@ -1048,6 +1072,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 */
@ -1263,6 +1290,9 @@
/* Define if EVP_DigestUpdate returns void */
/* #undef OPENSSL_EVP_DIGESTUPDATE_VOID */
/* libcrypto includes complete ECC support */
#define OPENSSL_HAS_ECC 1
/* libcrypto is missing AES 192 and 256 bit functions */
/* #undef OPENSSL_LOBOTOMISED_AES */
@ -1281,6 +1311,9 @@
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "openssh"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "Portable"
@ -1394,6 +1427,9 @@
/* Use libedit for sftp */
#define USE_LIBEDIT 1
/* Use Linux audit module */
/* #undef USE_LINUX_AUDIT */
/* Enable OpenSSL engine support */
#define USE_OPENSSL_ENGINE 1
@ -1406,6 +1442,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 */
@ -1429,7 +1468,7 @@
/* #undef WITH_SELINUX */
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel and VAX). */
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
#elif ! defined __LITTLE_ENDIAN__

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

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,10 @@ enum
# define SHUT_RDWR SHUT_RDWR
#endif
/*
* Definitions for IP type of service (ip_tos)
*/
#include <netinet/ip.h>
#ifndef IPTOS_LOWDELAY
# define IPTOS_LOWDELAY 0x10
# define IPTOS_THROUGHPUT 0x08
@ -50,6 +54,39 @@ enum
# define IPTOS_MINCOST IPTOS_LOWCOST
#endif /* IPTOS_LOWDELAY */
/*
* Definitions for DiffServ Codepoints as per RFC2474
*/
#include <netinet/in_systm.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__)

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

@ -100,6 +100,7 @@ seed_rng(void)
close(p[0]);
close(p[1]);
close(devnull);
closefrom(STDERR_FILENO + 1);
if (original_uid != original_euid &&
( seteuid(getuid()) == -1 ||
@ -157,7 +158,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:

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

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
crypto/openssh/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
crypto/openssh/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
crypto/openssh/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"

File diff suppressed because it is too large Load Diff

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

@ -274,7 +274,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;
@ -298,7 +298,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;
@ -312,7 +312,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!) */
@ -336,7 +337,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;
@ -364,7 +365,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;
@ -469,9 +470,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);
}
@ -877,11 +878,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);
}
/*
@ -897,16 +900,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);
@ -1210,7 +1217,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
@ -1501,11 +1508,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);
}
}
@ -1677,7 +1685,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);

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

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

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

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

@ -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.4.3 2011/02/06 02:24:17 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");
}
@ -205,17 +205,41 @@ ssh_selinux_change_context(const char *newname)
xfree(oldctx);
xfree(newctx);
}
void
ssh_selinux_setfscreatecon(const char *path)
{
security_context_t context;
if (!ssh_selinux_enabled())
return;
if (path == NULL) {
setfscreatecon(NULL);
return;
}
if (matchpathcon(path, 0700, &context) == 0)
setfscreatecon(context);
}
#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 +248,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 +282,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-linux.h,v 1.4 2009/12/08 02:39:48 dtucker Exp $ */
/* $Id: port-linux.h,v 1.4.10.1 2011/02/04 00:42:21 djm Exp $ */
/*
* Copyright (c) 2006 Damien Miller <djm@openbsd.org>
@ -24,6 +24,7 @@ int ssh_selinux_enabled(void);
void ssh_selinux_setup_pty(char *, const char *);
void ssh_selinux_setup_exec_context(char *);
void ssh_selinux_change_context(const char *);
void ssh_selinux_setfscreatecon(const char *);
#endif
#ifdef LINUX_OOM_ADJUST

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

@ -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
@ -21,6 +21,8 @@ __RCSID("$FreeBSD$");
#include <sys/sysctl.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <ctype.h>
#include <errno.h>
@ -135,6 +137,7 @@ typedef enum {
oHashKnownHosts,
oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
oKexAlgorithms, oIPQoS,
oVersionAddendum,
oDeprecated, oUnsupported
} OpCodes;
@ -244,6 +247,8 @@ static struct {
#else
{ "zeroknowledgepasswordauthentication", oUnsupported },
#endif
{ "kexalgorithms", oKexAlgorithms },
{ "ipqos", oIPQoS },
{ "versionaddendum", oVersionAddendum },
{ NULL, oBadOption }
@ -716,6 +721,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')
@ -976,6 +993,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;
@ -1102,6 +1136,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;
@ -1144,6 +1179,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;
}
/*
@ -1215,6 +1252,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;
@ -1238,6 +1276,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)
@ -1290,6 +1335,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,4 +1,4 @@
/* $OpenBSD: schnorr.c,v 1.3 2009/03/05 07:18:19 djm Exp $ */
/* $OpenBSD: schnorr.c,v 1.5 2010/12/03 23:49:26 djm Exp $ */
/* $FreeBSD$ */
/*
* Copyright (c) 2008 Damien Miller. All rights reserved.
@ -141,6 +141,10 @@ schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
error("%s: g_x < 1", __func__);
return -1;
}
if (BN_cmp(g_x, grp_p) >= 0) {
error("%s: g_x > g", __func__);
return -1;
}
h = g_v = r = tmp = v = NULL;
if ((bn_ctx = BN_CTX_new()) == NULL) {
@ -257,14 +261,19 @@ schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
const BIGNUM *r, const BIGNUM *e)
{
int success = -1;
BIGNUM *h, *g_xh, *g_r, *expected;
BIGNUM *h = NULL, *g_xh = NULL, *g_r = NULL, *gx_q = NULL;
BIGNUM *expected = NULL;
BN_CTX *bn_ctx;
SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__));
/* Avoid degenerate cases: g^0 yields a spoofable signature */
if (BN_cmp(g_x, BN_value_one()) <= 0) {
error("%s: g_x < 1", __func__);
error("%s: g_x <= 1", __func__);
return -1;
}
if (BN_cmp(g_x, grp_p) >= 0) {
error("%s: g_x >= p", __func__);
return -1;
}
@ -275,6 +284,7 @@ schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
}
if ((g_xh = BN_new()) == NULL ||
(g_r = BN_new()) == NULL ||
(gx_q = BN_new()) == NULL ||
(expected = BN_new()) == NULL) {
error("%s: BN_new", __func__);
goto out;
@ -283,6 +293,17 @@ schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
SCHNORR_DEBUG_BN((e, "%s: e = ", __func__));
SCHNORR_DEBUG_BN((r, "%s: r = ", __func__));
/* gx_q = (g^x)^q must === 1 mod p */
if (BN_mod_exp(gx_q, g_x, grp_q, grp_p, bn_ctx) == -1) {
error("%s: BN_mod_exp (g_x^q mod p)", __func__);
goto out;
}
if (BN_cmp(gx_q, BN_value_one()) != 0) {
error("%s: Invalid signature (g^x)^q != 1 mod p", __func__);
goto out;
}
SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__));
/* h = H(g || g^v || g^x || id) */
if ((h = schnorr_hash(grp_p, grp_q, grp_g, evp_md, e, g_x,
id, idlen)) == NULL) {
@ -317,9 +338,14 @@ schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
BN_CTX_free(bn_ctx);
if (h != NULL)
BN_clear_free(h);
BN_clear_free(g_xh);
BN_clear_free(g_r);
BN_clear_free(expected);
if (gx_q != NULL)
BN_clear_free(gx_q);
if (g_xh != NULL)
BN_clear_free(g_xh);
if (g_r != NULL)
BN_clear_free(g_r);
if (expected != NULL)
BN_clear_free(expected);
return success;
}

View File

@ -1,4 +1,3 @@
.\" -*- nroff -*-
.\"
.\" scp.1
.\"
@ -9,9 +8,9 @@
.\"
.\" Created: Sun May 7 00:14:37 1995 ylo
.\"
.\" $OpenBSD: scp.1,v 1.50 2010/02/08 10:50:20 markus Exp $
.\" $OpenBSD: scp.1,v 1.56 2010/12/09 14:13:32 jmc Exp $
.\"
.Dd February 8, 2010
.Dd December 9, 2010
.Dt SCP 1
.Os
.Sh NAME
@ -20,7 +19,7 @@
.Sh SYNOPSIS
.Nm scp
.Bk -words
.Op Fl 1246BCpqrv
.Op Fl 12346BCpqrv
.Op Fl c Ar cipher
.Op Fl F Ar ssh_config
.Op Fl i Ar identity_file
@ -76,6 +75,11 @@ to use protocol 1.
Forces
.Nm
to use protocol 2.
.It Fl 3
Copies between two remote hosts are transferred through the local host.
Without this option the data is copied directly between the two remote
hosts.
Note that this option disables the progress meter.
.It Fl 4
Forces
.Nm
@ -147,7 +151,9 @@ For full details of the options listed below, and their possible values, see
.It HostName
.It IdentityFile
.It IdentitiesOnly
.It IPQoS
.It KbdInteractiveDevices
.It KexAlgorithms
.It LogLevel
.It MACs
.It NoHostAuthenticationForLocalhost
@ -209,7 +215,7 @@ to print debugging messages about their progress.
This is helpful in
debugging connection, authentication, and configuration problems.
.El
.Pp
.Sh EXIT STATUS
.Ex -std scp
.Sh SEE ALSO
.Xr rcp 1 ,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: scp.c,v 1.166 2010/07/01 13:06:59 millert Exp $ */
/* $OpenBSD: scp.c,v 1.170 2010/12/09 14:13:33 jmc Exp $ */
/*
* scp - secure remote copy. This is basically patched BSD rcp which
* uses ssh to do the data transfer (instead of using rcmd).
@ -119,14 +119,15 @@ extern char *__progname;
#define COPY_BUFLEN 16384
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout);
void bwlimit(int);
int do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout);
/* Struct for addargs */
arglist args;
arglist remote_remote_args;
/* Bandwidth limit */
off_t limit_rate = 0;
long long limit_kbps = 0;
struct bwlimit bwlimit;
/* Name of current file being transferred. */
char *curfile;
@ -137,6 +138,12 @@ int verbose_mode = 0;
/* This is set to zero if the progressmeter is not desired. */
int showprogress = 1;
/*
* This is set to non-zero if remote-remote copy should be piped
* through this process.
*/
int throughlocal = 0;
/* This is the program to execute for the secured connection. ("ssh" or -S) */
char *ssh_program = _PATH_SSH_PROGRAM;
@ -287,6 +294,50 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
return 0;
}
/*
* This functions executes a command simlar to do_cmd(), but expects the
* input and output descriptors to be setup by a previous call to do_cmd().
* This way the input and output of two commands can be connected.
*/
int
do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout)
{
pid_t pid;
int status;
if (verbose_mode)
fprintf(stderr,
"Executing: 2nd program %s host %s, user %s, command %s\n",
ssh_program, host,
remuser ? remuser : "(unspecified)", cmd);
/* Fork a child to execute the command on the remote host using ssh. */
pid = fork();
if (pid == 0) {
dup2(fdin, 0);
dup2(fdout, 1);
replacearg(&args, 0, "%s", ssh_program);
if (remuser != NULL) {
addargs(&args, "-l");
addargs(&args, "%s", remuser);
}
addargs(&args, "--");
addargs(&args, "%s", host);
addargs(&args, "%s", cmd);
execvp(ssh_program, args.list);
perror(ssh_program);
exit(1);
} else if (pid == -1) {
fatal("fork: %s", strerror(errno));
}
while (waitpid(pid, &status, 0) == -1)
if (errno != EINTR)
fatal("do_cmd2: waitpid: %s", strerror(errno));
return 0;
}
typedef struct {
size_t cnt;
char *buf;
@ -312,15 +363,14 @@ void sink(int, char *[]);
void source(int, char *[]);
void tolocal(int, char *[]);
void toremote(char *, int, char *[]);
size_t scpio(ssize_t (*)(int, void *, size_t), int, void *, size_t, off_t *);
void usage(void);
int
main(int argc, char **argv)
{
int ch, fflag, tflag, status, n;
double speed;
char *targ, *endp, **newargv;
char *targ, **newargv;
const char *errstr;
extern char *optarg;
extern int optind;
@ -336,15 +386,16 @@ main(int argc, char **argv)
__progname = ssh_get_progname(argv[0]);
memset(&args, '\0', sizeof(args));
args.list = NULL;
memset(&remote_remote_args, '\0', sizeof(remote_remote_args));
args.list = remote_remote_args.list = NULL;
addargs(&args, "%s", ssh_program);
addargs(&args, "-x");
addargs(&args, "-oForwardAgent no");
addargs(&args, "-oPermitLocalCommand no");
addargs(&args, "-oClearAllForwardings yes");
addargs(&args, "-oForwardAgent=no");
addargs(&args, "-oPermitLocalCommand=no");
addargs(&args, "-oClearAllForwardings=yes");
fflag = tflag = 0;
while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1)
while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1)
switch (ch) {
/* User-visible flags. */
case '1':
@ -353,26 +404,37 @@ main(int argc, char **argv)
case '6':
case 'C':
addargs(&args, "-%c", ch);
addargs(&remote_remote_args, "-%c", ch);
break;
case '3':
throughlocal = 1;
break;
case 'o':
case 'c':
case 'i':
case 'F':
addargs(&remote_remote_args, "-%c", ch);
addargs(&remote_remote_args, "%s", optarg);
addargs(&args, "-%c", ch);
addargs(&args, "%s", optarg);
break;
case 'P':
addargs(&remote_remote_args, "-p");
addargs(&remote_remote_args, "%s", optarg);
addargs(&args, "-p");
addargs(&args, "%s", optarg);
break;
case 'B':
addargs(&args, "-oBatchmode yes");
addargs(&remote_remote_args, "-oBatchmode=yes");
addargs(&args, "-oBatchmode=yes");
break;
case 'l':
speed = strtod(optarg, &endp);
if (speed <= 0 || *endp != '\0')
limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024,
&errstr);
if (errstr != NULL)
usage();
limit_rate = speed * 1024;
limit_kbps *= 1024; /* kbps */
bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN);
break;
case 'p':
pflag = 1;
@ -385,10 +447,12 @@ main(int argc, char **argv)
break;
case 'v':
addargs(&args, "-v");
addargs(&remote_remote_args, "-v");
verbose_mode = 1;
break;
case 'q':
addargs(&args, "-q");
addargs(&remote_remote_args, "-q");
showprogress = 0;
break;
@ -474,41 +538,16 @@ main(int argc, char **argv)
exit(errs != 0);
}
/*
* atomicio-like wrapper that also applies bandwidth limits and updates
* the progressmeter counter.
*/
size_t
scpio(ssize_t (*f)(int, void *, size_t), int fd, void *_p, size_t l, off_t *c)
/* Callback from atomicio6 to update progress meter and limit bandwidth */
static int
scpio(void *_cnt, size_t s)
{
u_char *p = (u_char *)_p;
size_t offset;
ssize_t r;
struct pollfd pfd;
off_t *cnt = (off_t *)_cnt;
pfd.fd = fd;
pfd.events = f == read ? POLLIN : POLLOUT;
for (offset = 0; offset < l;) {
r = f(fd, p + offset, l - offset);
if (r == 0) {
errno = EPIPE;
return offset;
}
if (r < 0) {
if (errno == EINTR)
continue;
if (errno == EAGAIN || errno == EWOULDBLOCK) {
(void)poll(&pfd, 1, -1); /* Ignore errors */
continue;
}
return offset;
}
offset += (size_t)r;
*c += (off_t)r;
if (limit_rate)
bwlimit(r);
}
return offset;
*cnt += s;
if (limit_kbps > 0)
bandwidth_limit(&bwlimit, s);
return 0;
}
void
@ -517,6 +556,7 @@ toremote(char *targ, int argc, char **argv)
char *bp, *host, *src, *suser, *thost, *tuser, *arg;
arglist alist;
int i;
u_int j;
memset(&alist, '\0', sizeof(alist));
alist.list = NULL;
@ -544,15 +584,45 @@ toremote(char *targ, int argc, char **argv)
for (i = 0; i < argc - 1; i++) {
src = colon(argv[i]);
if (src) { /* remote to remote */
if (src && throughlocal) { /* extended remote to remote */
*src++ = 0;
if (*src == 0)
src = ".";
host = strrchr(argv[i], '@');
if (host) {
*host++ = 0;
host = cleanhostname(host);
suser = argv[i];
if (*suser == '\0')
suser = pwd->pw_name;
else if (!okname(suser))
continue;
} else {
host = cleanhostname(argv[i]);
suser = NULL;
}
xasprintf(&bp, "%s -f -- %s", cmd, src);
if (do_cmd(host, suser, bp, &remin, &remout) < 0)
exit(1);
(void) xfree(bp);
host = cleanhostname(thost);
xasprintf(&bp, "%s -t -- %s", cmd, targ);
if (do_cmd2(host, tuser, bp, remin, remout) < 0)
exit(1);
(void) xfree(bp);
(void) close(remin);
(void) close(remout);
remin = remout = -1;
} else if (src) { /* standard remote to remote */
freeargs(&alist);
addargs(&alist, "%s", ssh_program);
if (verbose_mode)
addargs(&alist, "-v");
addargs(&alist, "-x");
addargs(&alist, "-oClearAllForwardings yes");
addargs(&alist, "-oClearAllForwardings=yes");
addargs(&alist, "-n");
for (j = 0; j < remote_remote_args.num; j++) {
addargs(&alist, "%s",
remote_remote_args.list[j]);
}
*src++ = 0;
if (*src == 0)
src = ".";
@ -750,7 +820,7 @@ next: if (fd != -1) {
(void)atomicio(vwrite, remout, bp->buf, amt);
continue;
}
if (scpio(vwrite, remout, bp->buf, amt,
if (atomicio6(vwrite, remout, bp->buf, amt, scpio,
&statbytes) != amt)
haderr = errno;
}
@ -824,60 +894,6 @@ rsource(char *name, struct stat *statp)
(void) response();
}
void
bwlimit(int amount)
{
static struct timeval bwstart, bwend;
static int lamt, thresh = 16384;
u_int64_t waitlen;
struct timespec ts, rm;
if (!timerisset(&bwstart)) {
gettimeofday(&bwstart, NULL);
return;
}
lamt += amount;
if (lamt < thresh)
return;
gettimeofday(&bwend, NULL);
timersub(&bwend, &bwstart, &bwend);
if (!timerisset(&bwend))
return;
lamt *= 8;
waitlen = (double)1000000L * lamt / limit_rate;
bwstart.tv_sec = waitlen / 1000000L;
bwstart.tv_usec = waitlen % 1000000L;
if (timercmp(&bwstart, &bwend, >)) {
timersub(&bwstart, &bwend, &bwend);
/* Adjust the wait time */
if (bwend.tv_sec) {
thresh /= 2;
if (thresh < 2048)
thresh = 2048;
} else if (bwend.tv_usec < 10000) {
thresh *= 2;
if (thresh > COPY_BUFLEN * 4)
thresh = COPY_BUFLEN * 4;
}
TIMEVAL_TO_TIMESPEC(&bwend, &ts);
while (nanosleep(&ts, &rm) == -1) {
if (errno != EINTR)
break;
ts = rm;
}
}
lamt = 0;
gettimeofday(&bwstart, NULL);
}
void
sink(int argc, char **argv)
{
@ -1071,7 +1087,8 @@ bad: run_err("%s: %s", np, strerror(errno));
amt = size - i;
count += amt;
do {
j = scpio(read, remin, cp, amt, &statbytes);
j = atomicio6(read, remin, cp, amt,
scpio, &statbytes);
if (j == 0) {
run_err("%s", j != EPIPE ?
strerror(errno) :
@ -1197,7 +1214,7 @@ void
usage(void)
{
(void) fprintf(stderr,
"usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
"usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
" [-l limit] [-o ssh_option] [-P port] [-S program]\n"
" [[user@]host1:]file1 ... [[user@]host2:]file2\n");
exit(1);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.c,v 1.209 2010/06/22 04:22:59 djm Exp $ */
/* $OpenBSD: servconf.c,v 1.213 2010/11/13 23:27:50 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -16,6 +16,10 @@ __RCSID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netdb.h>
#include <pwd.h>
#include <stdio.h>
@ -111,6 +115,7 @@ initialize_server_options(ServerOptions *options)
options->num_deny_groups = 0;
options->ciphers = NULL;
options->macs = NULL;
options->kex_algorithms = NULL;
options->protocol = SSH_PROTO_UNKNOWN;
options->gateway_ports = -1;
options->num_subsystems = 0;
@ -134,6 +139,8 @@ initialize_server_options(ServerOptions *options)
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
options->authorized_principals_file = NULL;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
}
void
@ -156,6 +163,10 @@ fill_default_server_options(ServerOptions *options)
_PATH_HOST_RSA_KEY_FILE;
options->host_key_files[options->num_host_key_files++] =
_PATH_HOST_DSA_KEY_FILE;
#ifdef OPENSSL_HAS_ECC
options->host_key_files[options->num_host_key_files++] =
_PATH_HOST_ECDSA_KEY_FILE;
#endif
}
}
/* No certificates by default */
@ -258,16 +269,20 @@ fill_default_server_options(ServerOptions *options)
if (options->authorized_keys_file2 == NULL) {
/* authorized_keys_file2 falls back to authorized_keys_file */
if (options->authorized_keys_file != NULL)
options->authorized_keys_file2 = options->authorized_keys_file;
options->authorized_keys_file2 = xstrdup(options->authorized_keys_file);
else
options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
options->authorized_keys_file2 = xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2);
}
if (options->authorized_keys_file == NULL)
options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
options->authorized_keys_file = xstrdup(_PATH_SSH_USER_PERMITTED_KEYS);
if (options->permit_tun == -1)
options->permit_tun = SSH_TUNMODE_NO;
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;
/* Turn privilege separation on by default */
if (use_privsep == -1)
@ -314,6 +329,7 @@ typedef enum {
sUsePrivilegeSeparation, sAllowAgentForwarding,
sZeroKnowledgePasswordAuthentication, sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sKexAlgorithms, sIPQoS,
sVersionAddendum,
sDeprecated, sUnsupported
} ServerOpCodes;
@ -437,6 +453,8 @@ static struct {
{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
{ "ipqos", sIPQoS, SSHCFG_ALL },
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
{ NULL, sBadOption, 0 }
};
@ -667,7 +685,7 @@ process_server_config_line(ServerOptions *options, char *line,
const char *host, const char *address)
{
char *cp, **charptr, *arg, *p;
int cmdline = 0, *intptr, value, n;
int cmdline = 0, *intptr, value, value2, n;
SyslogFacility *log_facility_ptr;
LogLevel *log_level_ptr;
ServerOpCodes opcode;
@ -1133,6 +1151,18 @@ process_server_config_line(ServerOptions *options, char *line,
options->macs = xstrdup(arg);
break;
case sKexAlgorithms:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.",
filename, linenum);
if (!kex_names_valid(arg))
fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->kex_algorithms == NULL)
options->kex_algorithms = xstrdup(arg);
break;
case sProtocol:
intptr = &options->protocol;
arg = strdelim(&cp);
@ -1355,11 +1385,28 @@ process_server_config_line(ServerOptions *options, char *line,
charptr = &options->revoked_keys_file;
goto parse_filename;
case sIPQoS:
arg = strdelim(&cp);
if ((value = parse_ipqos(arg)) == -1)
fatal("%s line %d: Bad IPQoS value: %s",
filename, linenum, arg);
arg = strdelim(&cp);
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 sVersionAddendum:
ssh_version_set_addendum(strtok(cp, "\n"));
do {
arg = strdelim(&cp);
} while (arg != NULL && *arg != '\0');
ssh_version_set_addendum(strtok(cp, "\n"));
do {
arg = strdelim(&cp);
} while (arg != NULL && *arg != '\0');
break;
case sDeprecated:
@ -1472,6 +1519,8 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(x11_use_localhost);
M_CP_INTOPT(max_sessions);
M_CP_INTOPT(max_authtries);
M_CP_INTOPT(ip_qos_interactive);
M_CP_INTOPT(ip_qos_bulk);
M_CP_STROPT(banner);
if (preauth)
@ -1737,5 +1786,7 @@ dump_config(ServerOptions *o)
}
dump_cfg_string(sPermitTunnel, s);
printf("ipqos 0x%02x 0x%02x\n", o->ip_qos_interactive, o->ip_qos_bulk);
channel_print_adm_permitted_opens();
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.93 2010/05/07 11:30:30 djm Exp $ */
/* $OpenBSD: servconf.h,v 1.95 2010/11/13 23:27:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -70,8 +70,11 @@ typedef struct {
char *xauth_location; /* Location of xauth program */
int strict_modes; /* If true, require string home dir modes. */
int tcp_keep_alive; /* If true, set SO_KEEPALIVE. */
int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */
int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */
char *ciphers; /* Supported SSH2 ciphers. */
char *macs; /* Supported SSH2 macs. */
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
int protocol; /* Supported protocol versions. */
int gateway_ports; /* If true, allow remote connects to forwarded ports. */
SyslogFacility log_facility; /* Facility for system logging. */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.256 2010/06/25 07:20:04 djm Exp $ */
/* $OpenBSD: session.c,v 1.258 2010/11/25 04:10:09 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -586,7 +586,8 @@ do_exec_no_pty(Session *s, const char *command)
s->pid = pid;
/* Set interactive/non-interactive mode. */
packet_set_interactive(s->display != NULL);
packet_set_interactive(s->display != NULL,
options.ip_qos_interactive, options.ip_qos_bulk);
/*
* Clear loginmsg, since it's the child's responsibility to display
@ -740,7 +741,8 @@ do_exec_pty(Session *s, const char *command)
/* Enter interactive session. */
s->ptymaster = ptymaster;
packet_set_interactive(1);
packet_set_interactive(1,
options.ip_qos_interactive, options.ip_qos_bulk);
if (compat20) {
session_set_fds(s, ptyfd, fdout, -1, 1, 1);
} else {
@ -1481,36 +1483,16 @@ do_setusercontext(struct passwd *pw)
{
char *chroot_path, *tmp;
#ifdef WITH_SELINUX
/* Cache selinux status for later use */
(void)ssh_selinux_enabled();
#endif
platform_setusercontext(pw);
#ifndef HAVE_CYGWIN
if (getuid() == 0 || geteuid() == 0)
#endif /* HAVE_CYGWIN */
{
if (platform_privileged_uidswap()) {
#ifdef HAVE_LOGIN_CAP
# ifdef __bsdi__
setpgid(0, 0);
# endif
# ifdef USE_PAM
if (options.use_pam) {
do_pam_setcred(use_privsep);
}
# endif /* USE_PAM */
if (setusercontext(lc, pw, pw->pw_uid,
(LOGIN_SETALL & ~(LOGIN_SETENV|LOGIN_SETPATH|LOGIN_SETUSER))) < 0) {
perror("unable to set user context");
exit(1);
}
#else
# if defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
/* Sets login uid for accounting */
if (getluid() == -1 && setluid(pw->pw_uid) == -1)
error("setluid: %s", strerror(errno));
# endif /* defined(HAVE_GETLUID) && defined(HAVE_SETLUID) */
if (setlogin(pw->pw_name) < 0)
error("setlogin failed: %s", strerror(errno));
if (setgid(pw->pw_gid) < 0) {
@ -1523,50 +1505,9 @@ do_setusercontext(struct passwd *pw)
exit(1);
}
endgrent();
# ifdef 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(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 */
# ifdef USE_LIBIAF
if (set_id(pw->pw_name) != 0) {
exit(1);
}
# endif /* USE_LIBIAF */
#endif
#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
platform_setusercontext_post_groups(pw);
if (options.chroot_directory != NULL &&
strcasecmp(options.chroot_directory, "none") != 0) {
@ -1640,8 +1581,6 @@ launch_login(struct passwd *pw, const char *hostname)
static void
child_close_fds(void)
{
int i;
if (packet_get_connection_in() == packet_get_connection_out())
close(packet_get_connection_in());
else {
@ -1667,8 +1606,7 @@ child_close_fds(void)
* initgroups, because at least on Solaris 2.3 it leaves file
* descriptors open.
*/
for (i = 3; i < 64; i++)
close(i);
closefrom(STDERR_FILENO + 1);
}
/*

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-client.c,v 1.92 2010/07/19 03:16:33 djm Exp $ */
/* $OpenBSD: sftp-client.c,v 1.94 2010/12/04 00:18:01 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@ -75,15 +75,28 @@ struct sftp_conn {
#define SFTP_EXT_POSIX_RENAME 0x00000001
#define SFTP_EXT_STATVFS 0x00000002
#define SFTP_EXT_FSTATVFS 0x00000004
#define SFTP_EXT_HARDLINK 0x00000008
u_int exts;
u_int64_t limit_kbps;
struct bwlimit bwlimit_in, bwlimit_out;
};
static char *
get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...)
__attribute__((format(printf, 4, 5)));
get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len,
const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
/* ARGSUSED */
static int
sftpio(void *_bwlimit, size_t amount)
{
struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
bandwidth_limit(bwlimit, amount);
return 0;
}
static void
send_msg(int fd, Buffer *m)
send_msg(struct sftp_conn *conn, Buffer *m)
{
u_char mlen[4];
struct iovec iov[2];
@ -98,19 +111,22 @@ send_msg(int fd, Buffer *m)
iov[1].iov_base = buffer_ptr(m);
iov[1].iov_len = buffer_len(m);
if (atomiciov(writev, fd, iov, 2) != buffer_len(m) + sizeof(mlen))
if (atomiciov6(writev, conn->fd_out, iov, 2,
conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) !=
buffer_len(m) + sizeof(mlen))
fatal("Couldn't send packet: %s", strerror(errno));
buffer_clear(m);
}
static void
get_msg(int fd, Buffer *m)
get_msg(struct sftp_conn *conn, Buffer *m)
{
u_int msg_len;
buffer_append_space(m, 4);
if (atomicio(read, fd, buffer_ptr(m), 4) != 4) {
if (atomicio6(read, conn->fd_in, buffer_ptr(m), 4,
conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
if (errno == EPIPE)
fatal("Connection closed");
else
@ -122,7 +138,9 @@ get_msg(int fd, Buffer *m)
fatal("Received message too long %u", msg_len);
buffer_append_space(m, msg_len);
if (atomicio(read, fd, buffer_ptr(m), msg_len) != msg_len) {
if (atomicio6(read, conn->fd_in, buffer_ptr(m), msg_len,
conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in)
!= msg_len) {
if (errno == EPIPE)
fatal("Connection closed");
else
@ -131,7 +149,7 @@ get_msg(int fd, Buffer *m)
}
static void
send_string_request(int fd, u_int id, u_int code, char *s,
send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s,
u_int len)
{
Buffer msg;
@ -140,14 +158,14 @@ send_string_request(int fd, u_int id, u_int code, char *s,
buffer_put_char(&msg, code);
buffer_put_int(&msg, id);
buffer_put_string(&msg, s, len);
send_msg(fd, &msg);
debug3("Sent message fd %d T:%u I:%u", fd, code, id);
send_msg(conn, &msg);
debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
buffer_free(&msg);
}
static void
send_string_attrs_request(int fd, u_int id, u_int code, char *s,
u_int len, Attrib *a)
send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
char *s, u_int len, Attrib *a)
{
Buffer msg;
@ -156,19 +174,19 @@ send_string_attrs_request(int fd, u_int id, u_int code, char *s,
buffer_put_int(&msg, id);
buffer_put_string(&msg, s, len);
encode_attrib(&msg, a);
send_msg(fd, &msg);
debug3("Sent message fd %d T:%u I:%u", fd, code, id);
send_msg(conn, &msg);
debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
buffer_free(&msg);
}
static u_int
get_status(int fd, u_int expected_id)
get_status(struct sftp_conn *conn, u_int expected_id)
{
Buffer msg;
u_int type, id, status;
buffer_init(&msg);
get_msg(fd, &msg);
get_msg(conn, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);
@ -183,11 +201,12 @@ get_status(int fd, u_int expected_id)
debug3("SSH2_FXP_STATUS %u", status);
return(status);
return status;
}
static char *
get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...)
get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len,
const char *errfmt, ...)
{
Buffer msg;
u_int type, id;
@ -201,7 +220,7 @@ get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...)
va_end(args);
buffer_init(&msg);
get_msg(fd, &msg);
get_msg(conn, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);
@ -225,14 +244,14 @@ get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...)
}
static Attrib *
get_decode_stat(int fd, u_int expected_id, int quiet)
get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
{
Buffer msg;
u_int type, id;
Attrib *a;
buffer_init(&msg);
get_msg(fd, &msg);
get_msg(conn, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);
@ -260,14 +279,14 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
}
static int
get_decode_statvfs(int fd, struct sftp_statvfs *st, u_int expected_id,
int quiet)
get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
u_int expected_id, int quiet)
{
Buffer msg;
u_int type, id, flag;
buffer_init(&msg);
get_msg(fd, &msg);
get_msg(conn, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);
@ -311,21 +330,29 @@ get_decode_statvfs(int fd, struct sftp_statvfs *st, u_int expected_id,
}
struct sftp_conn *
do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
u_int64_t limit_kbps)
{
u_int type, exts = 0;
int version;
u_int type;
Buffer msg;
struct sftp_conn *ret;
ret = xmalloc(sizeof(*ret));
ret->fd_in = fd_in;
ret->fd_out = fd_out;
ret->transfer_buflen = transfer_buflen;
ret->num_requests = num_requests;
ret->exts = 0;
ret->limit_kbps = 0;
buffer_init(&msg);
buffer_put_char(&msg, SSH2_FXP_INIT);
buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
send_msg(fd_out, &msg);
send_msg(ret, &msg);
buffer_clear(&msg);
get_msg(fd_in, &msg);
get_msg(ret, &msg);
/* Expecting a VERSION reply */
if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) {
@ -334,9 +361,9 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
buffer_free(&msg);
return(NULL);
}
version = buffer_get_int(&msg);
ret->version = buffer_get_int(&msg);
debug2("Remote version: %d", version);
debug2("Remote version: %u", ret->version);
/* Check for extensions */
while (buffer_len(&msg) > 0) {
@ -346,15 +373,19 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
if (strcmp(name, "posix-rename@openssh.com") == 0 &&
strcmp(value, "1") == 0) {
exts |= SFTP_EXT_POSIX_RENAME;
ret->exts |= SFTP_EXT_POSIX_RENAME;
known = 1;
} else if (strcmp(name, "statvfs@openssh.com") == 0 &&
strcmp(value, "2") == 0) {
exts |= SFTP_EXT_STATVFS;
ret->exts |= SFTP_EXT_STATVFS;
known = 1;
} if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
} else if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
strcmp(value, "2") == 0) {
exts |= SFTP_EXT_FSTATVFS;
ret->exts |= SFTP_EXT_FSTATVFS;
known = 1;
} else if (strcmp(name, "hardlink@openssh.com") == 0 &&
strcmp(value, "1") == 0) {
ret->exts |= SFTP_EXT_HARDLINK;
known = 1;
}
if (known) {
@ -369,26 +400,25 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
buffer_free(&msg);
ret = xmalloc(sizeof(*ret));
ret->fd_in = fd_in;
ret->fd_out = fd_out;
ret->transfer_buflen = transfer_buflen;
ret->num_requests = num_requests;
ret->version = version;
ret->msg_id = 1;
ret->exts = exts;
/* Some filexfer v.0 servers don't support large packets */
if (version == 0)
if (ret->version == 0)
ret->transfer_buflen = MIN(ret->transfer_buflen, 20480);
return(ret);
ret->limit_kbps = limit_kbps;
if (ret->limit_kbps > 0) {
bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps,
ret->transfer_buflen);
bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps,
ret->transfer_buflen);
}
return ret;
}
u_int
sftp_proto_version(struct sftp_conn *conn)
{
return(conn->version);
return conn->version;
}
int
@ -403,16 +433,16 @@ do_close(struct sftp_conn *conn, char *handle, u_int handle_len)
buffer_put_char(&msg, SSH2_FXP_CLOSE);
buffer_put_int(&msg, id);
buffer_put_string(&msg, handle, handle_len);
send_msg(conn->fd_out, &msg);
send_msg(conn, &msg);
debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
status = get_status(conn->fd_in, id);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't close file: %s", fx2txt(status));
buffer_free(&msg);
return(status);
return status;
}
@ -430,14 +460,14 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
buffer_put_char(&msg, SSH2_FXP_OPENDIR);
buffer_put_int(&msg, id);
buffer_put_cstring(&msg, path);
send_msg(conn->fd_out, &msg);
send_msg(conn, &msg);
buffer_clear(&msg);
handle = get_handle(conn->fd_in, id, &handle_len,
handle = get_handle(conn, id, &handle_len,
"remote readdir(\"%s\")", path);
if (handle == NULL)
return(-1);
return -1;
if (dir) {
ents = 0;
@ -454,11 +484,11 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
buffer_put_char(&msg, SSH2_FXP_READDIR);
buffer_put_int(&msg, id);
buffer_put_string(&msg, handle, handle_len);
send_msg(conn->fd_out, &msg);
send_msg(conn, &msg);
buffer_clear(&msg);
get_msg(conn->fd_in, &msg);
get_msg(conn, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);
@ -537,7 +567,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
**dir = NULL;
}
return(0);
return 0;
}
int
@ -566,9 +596,8 @@ do_rm(struct sftp_conn *conn, char *path)
debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
id = conn->msg_id++;
send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path,
strlen(path));
status = get_status(conn->fd_in, id);
send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't delete file: %s", fx2txt(status));
return(status);
@ -580,10 +609,10 @@ do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int printflag)
u_int status, id;
id = conn->msg_id++;
send_string_attrs_request(conn->fd_out, id, SSH2_FXP_MKDIR, path,
send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path,
strlen(path), a);
status = get_status(conn->fd_in, id);
status = get_status(conn, id);
if (status != SSH2_FX_OK && printflag)
error("Couldn't create directory: %s", fx2txt(status));
@ -596,10 +625,10 @@ do_rmdir(struct sftp_conn *conn, char *path)
u_int status, id;
id = conn->msg_id++;
send_string_request(conn->fd_out, id, SSH2_FXP_RMDIR, path,
send_string_request(conn, id, SSH2_FXP_RMDIR, path,
strlen(path));
status = get_status(conn->fd_in, id);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't remove directory: %s", fx2txt(status));
@ -613,11 +642,11 @@ do_stat(struct sftp_conn *conn, char *path, int quiet)
id = conn->msg_id++;
send_string_request(conn->fd_out, id,
send_string_request(conn, id,
conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
path, strlen(path));
return(get_decode_stat(conn->fd_in, id, quiet));
return(get_decode_stat(conn, id, quiet));
}
Attrib *
@ -634,10 +663,10 @@ do_lstat(struct sftp_conn *conn, char *path, int quiet)
}
id = conn->msg_id++;
send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path,
send_string_request(conn, id, SSH2_FXP_LSTAT, path,
strlen(path));
return(get_decode_stat(conn->fd_in, id, quiet));
return(get_decode_stat(conn, id, quiet));
}
#ifdef notyet
@ -647,10 +676,10 @@ do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
u_int id;
id = conn->msg_id++;
send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle,
send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
handle_len);
return(get_decode_stat(conn->fd_in, id, quiet));
return(get_decode_stat(conn, id, quiet));
}
#endif
@ -660,10 +689,10 @@ do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
u_int status, id;
id = conn->msg_id++;
send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path,
send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path,
strlen(path), a);
status = get_status(conn->fd_in, id);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't setstat on \"%s\": %s", path,
fx2txt(status));
@ -678,10 +707,10 @@ do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len,
u_int status, id;
id = conn->msg_id++;
send_string_attrs_request(conn->fd_out, id, SSH2_FXP_FSETSTAT, handle,
send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle,
handle_len, a);
status = get_status(conn->fd_in, id);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't fsetstat: %s", fx2txt(status));
@ -697,12 +726,12 @@ do_realpath(struct sftp_conn *conn, char *path)
Attrib *a;
expected_id = id = conn->msg_id++;
send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path,
send_string_request(conn, id, SSH2_FXP_REALPATH, path,
strlen(path));
buffer_init(&msg);
get_msg(conn->fd_in, &msg);
get_msg(conn, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);
@ -756,13 +785,13 @@ do_rename(struct sftp_conn *conn, char *oldpath, char *newpath)
}
buffer_put_cstring(&msg, oldpath);
buffer_put_cstring(&msg, newpath);
send_msg(conn->fd_out, &msg);
send_msg(conn, &msg);
debug3("Sent message %s \"%s\" -> \"%s\"",
(conn->exts & SFTP_EXT_POSIX_RENAME) ? "posix-rename@openssh.com" :
"SSH2_FXP_RENAME", oldpath, newpath);
buffer_free(&msg);
status = get_status(conn->fd_in, id);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
newpath, fx2txt(status));
@ -770,6 +799,39 @@ do_rename(struct sftp_conn *conn, char *oldpath, char *newpath)
return(status);
}
int
do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath)
{
Buffer msg;
u_int status, id;
buffer_init(&msg);
/* Send link request */
id = conn->msg_id++;
if ((conn->exts & SFTP_EXT_HARDLINK) == 0) {
error("Server does not support hardlink@openssh.com extension");
return -1;
}
buffer_put_char(&msg, SSH2_FXP_EXTENDED);
buffer_put_int(&msg, id);
buffer_put_cstring(&msg, "hardlink@openssh.com");
buffer_put_cstring(&msg, oldpath);
buffer_put_cstring(&msg, newpath);
send_msg(conn, &msg);
debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
oldpath, newpath);
buffer_free(&msg);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't link file \"%s\" to \"%s\": %s", oldpath,
newpath, fx2txt(status));
return(status);
}
int
do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
{
@ -789,12 +851,12 @@ do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
buffer_put_int(&msg, id);
buffer_put_cstring(&msg, oldpath);
buffer_put_cstring(&msg, newpath);
send_msg(conn->fd_out, &msg);
send_msg(conn, &msg);
debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
newpath);
buffer_free(&msg);
status = get_status(conn->fd_in, id);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
newpath, fx2txt(status));
@ -812,12 +874,11 @@ do_readlink(struct sftp_conn *conn, char *path)
Attrib *a;
expected_id = id = conn->msg_id++;
send_string_request(conn->fd_out, id, SSH2_FXP_READLINK, path,
strlen(path));
send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
buffer_init(&msg);
get_msg(conn->fd_in, &msg);
get_msg(conn, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);
@ -871,10 +932,10 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
buffer_put_int(&msg, id);
buffer_put_cstring(&msg, "statvfs@openssh.com");
buffer_put_cstring(&msg, path);
send_msg(conn->fd_out, &msg);
send_msg(conn, &msg);
buffer_free(&msg);
return get_decode_statvfs(conn->fd_in, st, id, quiet);
return get_decode_statvfs(conn, st, id, quiet);
}
#ifdef notyet
@ -898,16 +959,16 @@ do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
buffer_put_int(&msg, id);
buffer_put_cstring(&msg, "fstatvfs@openssh.com");
buffer_put_string(&msg, handle, handle_len);
send_msg(conn->fd_out, &msg);
send_msg(conn, &msg);
buffer_free(&msg);
return get_decode_statvfs(conn->fd_in, st, id, quiet);
return get_decode_statvfs(conn, st, id, quiet);
}
#endif
static void
send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
char *handle, u_int handle_len)
send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
u_int len, char *handle, u_int handle_len)
{
Buffer msg;
@ -918,7 +979,7 @@ send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
buffer_put_string(&msg, handle, handle_len);
buffer_put_int64(&msg, offset);
buffer_put_int(&msg, len);
send_msg(fd_out, &msg);
send_msg(conn, &msg);
buffer_free(&msg);
}
@ -976,10 +1037,10 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
buffer_put_int(&msg, SSH2_FXF_READ);
attrib_clear(&junk); /* Send empty attributes */
encode_attrib(&msg, &junk);
send_msg(conn->fd_out, &msg);
send_msg(conn, &msg);
debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
handle = get_handle(conn->fd_in, id, &handle_len,
handle = get_handle(conn, id, &handle_len,
"remote open(\"%s\")", remote_path);
if (handle == NULL) {
buffer_free(&msg);
@ -1032,12 +1093,12 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
offset += buflen;
num_req++;
TAILQ_INSERT_TAIL(&requests, req, tq);
send_read_request(conn->fd_out, req->id, req->offset,
send_read_request(conn, req->id, req->offset,
req->len, handle, handle_len);
}
buffer_clear(&msg);
get_msg(conn->fd_in, &msg);
get_msg(conn, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);
debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
@ -1092,7 +1153,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
req->id = conn->msg_id++;
req->len -= len;
req->offset += len;
send_read_request(conn->fd_out, req->id,
send_read_request(conn, req->id,
req->offset, req->len, handle, handle_len);
/* Reduce the request size */
if (len < buflen)
@ -1327,12 +1388,12 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
buffer_put_cstring(&msg, remote_path);
buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC);
encode_attrib(&msg, &a);
send_msg(conn->fd_out, &msg);
send_msg(conn, &msg);
debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
buffer_clear(&msg);
handle = get_handle(conn->fd_in, id, &handle_len,
handle = get_handle(conn, id, &handle_len,
"remote open(\"%s\")", remote_path);
if (handle == NULL) {
close(local_fd);
@ -1381,7 +1442,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
buffer_put_string(&msg, handle, handle_len);
buffer_put_int64(&msg, offset);
buffer_put_string(&msg, data, len);
send_msg(conn->fd_out, &msg);
send_msg(conn, &msg);
debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
id, (unsigned long long)offset, len);
} else if (TAILQ_FIRST(&acks) == NULL)
@ -1395,7 +1456,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
u_int r_id;
buffer_clear(&msg);
get_msg(conn->fd_in, &msg);
get_msg(conn, &msg);
type = buffer_get_char(&msg);
r_id = buffer_get_int(&msg);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-client.h,v 1.18 2009/08/18 18:36:20 djm Exp $ */
/* $OpenBSD: sftp-client.h,v 1.20 2010/12/04 00:18:01 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
@ -51,7 +51,7 @@ struct sftp_statvfs {
* Initialise a SSH filexfer connection. Returns NULL on error or
* a pointer to a initialized sftp_conn struct on success.
*/
struct sftp_conn *do_init(int, int, u_int, u_int);
struct sftp_conn *do_init(int, int, u_int, u_int, u_int64_t);
u_int sftp_proto_version(struct sftp_conn *);
@ -94,6 +94,9 @@ int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int);
/* Rename 'oldpath' to 'newpath' */
int do_rename(struct sftp_conn *, char *, char *);
/* Link 'oldpath' to 'newpath' */
int do_hardlink(struct sftp_conn *, char *, char *);
/* Rename 'oldpath' to 'newpath' */
int do_symlink(struct sftp_conn *, char *, char *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-server.c,v 1.91 2010/01/13 01:40:16 djm Exp $ */
/* $OpenBSD: sftp-server.c,v 1.93 2010/12/04 00:18:01 djm Exp $ */
/*
* Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
*
@ -535,6 +535,9 @@ process_init(void)
/* fstatvfs extension */
buffer_put_cstring(&msg, "fstatvfs@openssh.com");
buffer_put_cstring(&msg, "2"); /* version */
/* hardlink extension */
buffer_put_cstring(&msg, "hardlink@openssh.com");
buffer_put_cstring(&msg, "1"); /* version */
send_msg(&msg);
buffer_free(&msg);
}
@ -1222,6 +1225,27 @@ process_extended_fstatvfs(u_int32_t id)
send_statvfs(id, &st);
}
static void
process_extended_hardlink(u_int32_t id)
{
char *oldpath, *newpath;
int ret, status;
oldpath = get_string(NULL);
newpath = get_string(NULL);
debug3("request %u: hardlink", id);
logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath);
if (readonly)
status = SSH2_FX_PERMISSION_DENIED;
else {
ret = link(oldpath, newpath);
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
}
send_status(id, status);
xfree(oldpath);
xfree(newpath);
}
static void
process_extended(void)
{
@ -1236,6 +1260,8 @@ process_extended(void)
process_extended_statvfs(id);
else if (strcmp(request, "fstatvfs@openssh.com") == 0)
process_extended_fstatvfs(id);
else if (strcmp(request, "hardlink@openssh.com") == 0)
process_extended_hardlink(id);
else
send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */
xfree(request);
@ -1377,8 +1403,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
ssize_t len, olen, set_size;
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
char *cp, buf[4*4096];
const char *errmsg;
mode_t mask;
long mask;
extern char *optarg;
extern char *__progname;
@ -1412,11 +1437,12 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
error("Invalid log facility \"%s\"", optarg);
break;
case 'u':
mask = (mode_t)strtonum(optarg, 0, 0777, &errmsg);
if (errmsg != NULL)
fatal("Invalid umask \"%s\": %s",
optarg, errmsg);
(void)umask(mask);
errno = 0;
mask = strtol(optarg, &cp, 8);
if (mask < 0 || mask > 0777 || *cp != '\0' ||
cp == optarg || (mask == 0 && errno != 0))
fatal("Invalid umask \"%s\"", optarg);
(void)umask((mode_t)mask);
break;
case 'h':
default:

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: sftp.1,v 1.83 2010/02/08 10:50:20 markus Exp $
.\" $OpenBSD: sftp.1,v 1.88 2010/12/04 00:18:01 djm Exp $
.\" $FreeBSD$
.\"
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
@ -23,7 +23,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd February 8, 2010
.Dd December 4, 2010
.Dt SFTP 1
.Os
.Sh NAME
@ -39,6 +39,7 @@
.Op Fl D Ar sftp_server_path
.Op Fl F Ar ssh_config
.Op Fl i Ar identity_file
.Op Fl l Ar limit
.Op Fl o Ar ssh_option
.Op Fl P Ar port
.Op Fl R Ar num_requests
@ -50,9 +51,11 @@
.Oo Ar user Ns @ Oc Ns
.Ar host Ns Op : Ns Ar
.Nm sftp
.Oo Ar user Ns @ Oc Ns
.Oo
.Ar user Ns @ Oc Ns
.Ar host Ns Oo : Ns Ar dir Ns
.Op Ar / Oc
.Op Ar /
.Oc
.Nm sftp
.Fl b Ar batchfile
.Oo Ar user Ns @ Oc Ns Ar host
@ -126,7 +129,7 @@ commands fail:
.Ic get , put , rename , ln ,
.Ic rm , mkdir , chdir , ls ,
.Ic lchdir , chmod , chown ,
.Ic chgrp , lpwd , df ,
.Ic chgrp , lpwd , df , symlink ,
and
.Ic lmkdir .
Termination on error can be suppressed on a command by command basis by
@ -158,6 +161,8 @@ Selects the file from which the identity (private key) for public key
authentication is read.
This option is directly passed to
.Xr ssh 1 .
.It Fl l Ar limit
Limits the used bandwidth, specified in Kbit/s.
.It Fl o Ar ssh_option
Can be used to pass options to
.Nm ssh
@ -197,7 +202,9 @@ For full details of the options listed below, and their possible values, see
.It HostName
.It IdentityFile
.It IdentitiesOnly
.It IPQoS
.It KbdInteractiveDevices
.It KexAlgorithms
.It LogLevel
.It MACs
.It NoHostAuthenticationForLocalhost
@ -386,11 +393,19 @@ characters and may match multiple files.
.It Ic lmkdir Ar path
Create local directory specified by
.Ar path .
.It Ic ln Ar oldpath Ar newpath
Create a symbolic link from
.It Xo Ic ln
.Op Fl s
.Ar oldpath
.Ar newpath
.Xc
Create a link from
.Ar oldpath
to
.Ar newpath .
If the
.Fl s
flag is specified the created link is a symbolic link, otherwise it is
a hard link.
.It Ic lpwd
Print local working directory.
.It Xo Ic ls

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp.c,v 1.125 2010/06/18 00:58:39 djm Exp $ */
/* $OpenBSD: sftp.c,v 1.132 2010/12/04 00:18:01 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@ -132,6 +132,7 @@ extern char *__progname;
#define I_GET 5
#define I_HELP 6
#define I_LCHDIR 7
#define I_LINK 25
#define I_LLS 8
#define I_LMKDIR 9
#define I_LPWD 10
@ -176,7 +177,7 @@ static const struct CMD cmds[] = {
{ "lchdir", I_LCHDIR, LOCAL },
{ "lls", I_LLS, LOCAL },
{ "lmkdir", I_LMKDIR, LOCAL },
{ "ln", I_SYMLINK, REMOTE },
{ "ln", I_LINK, REMOTE },
{ "lpwd", I_LPWD, LOCAL },
{ "ls", I_LS, REMOTE },
{ "lumask", I_LUMASK, NOARGS },
@ -240,7 +241,7 @@ help(void)
"lcd path Change local directory to 'path'\n"
"lls [ls-options [path]] Display local directory listing\n"
"lmkdir path Create local directory\n"
"ln oldpath newpath Symlink remote file\n"
"ln [-s] oldpath newpath Link remote file (-s for symlink)\n"
"lpwd Print local working directory\n"
"ls [-1afhlnrSt] [path] Display remote directory listing\n"
"lumask umask Set local umask to 'umask'\n"
@ -269,7 +270,7 @@ local_do_shell(const char *args)
if (!*args)
args = NULL;
if ((shell = getenv("SHELL")) == NULL)
if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
shell = _PATH_BSHELL;
if ((pid = fork()) == -1)
@ -376,6 +377,30 @@ parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag,
return optind;
}
static int
parse_link_flags(const char *cmd, char **argv, int argc, int *sflag)
{
extern int opterr, optind, optopt, optreset;
int ch;
optind = optreset = 1;
opterr = 0;
*sflag = 0;
while ((ch = getopt(argc, argv, "s")) != -1) {
switch (ch) {
case 's':
*sflag = 1;
break;
default:
error("%s: Invalid flag -%c", cmd, optopt);
return -1;
}
}
return optind;
}
static int
parse_ls_flags(char **argv, int argc, int *lflag)
{
@ -758,18 +783,22 @@ static int
do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
int lflag)
{
glob_t g;
u_int i, c = 1, colspace = 0, columns = 1;
Attrib *a = NULL;
char *fname, *lname;
glob_t g;
int err;
struct winsize ws;
u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80;
memset(&g, 0, sizeof(g));
if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE,
NULL, &g) || (g.gl_pathc && !g.gl_matchc)) {
if (remote_glob(conn, path,
GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT, NULL, &g) ||
(g.gl_pathc && !g.gl_matchc)) {
if (g.gl_pathc)
globfree(&g);
error("Can't ls: \"%s\" not found", path);
return (-1);
return -1;
}
if (interrupted)
@ -779,59 +808,35 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
* If the glob returns a single match and it is a directory,
* then just list its contents.
*/
if (g.gl_matchc == 1) {
if ((a = do_lstat(conn, g.gl_pathv[0], 1)) == NULL) {
globfree(&g);
return (-1);
}
if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
S_ISDIR(a->perm)) {
int err;
err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag);
globfree(&g);
return (err);
}
if (g.gl_matchc == 1 && g.gl_statv[0] != NULL &&
S_ISDIR(g.gl_statv[0]->st_mode)) {
err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag);
globfree(&g);
return err;
}
if (!(lflag & LS_SHORT_VIEW)) {
u_int m = 0, width = 80;
struct winsize ws;
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
width = ws.ws_col;
if (!(lflag & LS_SHORT_VIEW)) {
/* Count entries for sort and find longest filename */
for (i = 0; g.gl_pathv[i]; i++)
m = MAX(m, strlen(g.gl_pathv[i]));
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
width = ws.ws_col;
columns = width / (m + 2);
columns = MAX(columns, 1);
colspace = width / columns;
}
for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) {
char *fname;
fname = path_strip(g.gl_pathv[i], strip_path);
if (lflag & LS_LONG_VIEW) {
char *lname;
struct stat sb;
/*
* XXX: this is slow - 1 roundtrip per path
* A solution to this is to fork glob() and
* build a sftp specific version which keeps the
* attribs (which currently get thrown away)
* that the server returns as well as the filenames.
*/
memset(&sb, 0, sizeof(sb));
if (a == NULL)
a = do_lstat(conn, g.gl_pathv[i], 1);
if (a != NULL)
attrib_to_stat(a, &sb);
lname = ls_file(fname, &sb, 1, (lflag & LS_SI_UNITS));
if (g.gl_statv[i] == NULL) {
error("no stat information for %s", fname);
continue;
}
lname = ls_file(fname, g.gl_statv[i], 1,
(lflag & LS_SI_UNITS));
printf("%s\n", lname);
xfree(lname);
} else {
@ -852,7 +857,7 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
if (g.gl_pathc)
globfree(&g);
return (0);
return 0;
}
static int
@ -1108,7 +1113,7 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
static int
parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
int *hflag, unsigned long *n_arg, char **path1, char **path2)
int *hflag, int *sflag, unsigned long *n_arg, char **path1, char **path2)
{
const char *cmd, *cp = *cpp;
char *cp2, **argv;
@ -1158,7 +1163,8 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
switch (cmdnum) {
case I_GET:
case I_PUT:
if ((optidx = parse_getput_flags(cmd, argv, argc, pflag, rflag)) == -1)
if ((optidx = parse_getput_flags(cmd, argv, argc,
pflag, rflag)) == -1)
return -1;
/* Get first pathname (mandatory) */
if (argc - optidx < 1) {
@ -1174,8 +1180,11 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
undo_glob_escape(*path2);
}
break;
case I_RENAME:
case I_LINK:
if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
return -1;
case I_SYMLINK:
case I_RENAME:
if (argc - optidx < 2) {
error("You must specify two paths after a %s "
"command.", cmd);
@ -1278,7 +1287,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
int err_abort)
{
char *path1, *path2, *tmp;
int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, cmdnum, i;
int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0;
int cmdnum, i;
unsigned long n_arg = 0;
Attrib a, *aa;
char path_buf[MAXPATHLEN];
@ -1286,8 +1296,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
glob_t g;
path1 = path2 = NULL;
cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag, &n_arg,
&path1, &path2);
cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag,
&sflag, &n_arg, &path1, &path2);
if (iflag != 0)
err_abort = 0;
@ -1315,8 +1325,11 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
err = do_rename(conn, path1, path2);
break;
case I_SYMLINK:
sflag = 1;
case I_LINK:
path1 = make_absolute(path1, *pwd);
path2 = make_absolute(path2, *pwd);
err = do_symlink(conn, path1, path2);
err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2);
break;
case I_RM:
path1 = make_absolute(path1, *pwd);
@ -1745,6 +1758,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
case '"':
case '\\':
case '\t':
case '[':
case ' ':
if (quote == '\0' || tmp2[i] == quote) {
if (el_insertstr(el, ins) == -1)
@ -1874,7 +1888,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
/* Tab Completion */
el_set(el, EL_ADDFN, "ftp-complete",
"Context senstive argument completion", complete);
"Context sensitive argument completion", complete);
complete_ctx.conn = conn;
complete_ctx.remote_pathp = &remote_path;
el_set(el, EL_CLIENTDATA, (void*)&complete_ctx);
@ -2054,7 +2068,7 @@ usage(void)
fprintf(stderr,
"usage: %s [-1246Cpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
" [-D sftp_server_path] [-F ssh_config] "
"[-i identity_file]\n"
"[-i identity_file] [-l limit]\n"
" [-o ssh_option] [-P port] [-R num_requests] "
"[-S program]\n"
" [-s subsystem | sftp_server] host\n"
@ -2073,6 +2087,7 @@ main(int argc, char **argv)
int debug_level = 0, sshver = 2;
char *file1 = NULL, *sftp_server = NULL;
char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL;
const char *errstr;
LogLevel ll = SYSLOG_LEVEL_INFO;
arglist args;
extern int optind;
@ -2080,6 +2095,7 @@ main(int argc, char **argv)
struct sftp_conn *conn;
size_t copy_buffer_len = DEFAULT_COPY_BUFLEN;
size_t num_requests = DEFAULT_NUM_REQUESTS;
long long limit_kbps = 0;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@ -2097,7 +2113,7 @@ main(int argc, char **argv)
infile = stdin;
while ((ch = getopt(argc, argv,
"1246hpqrvCc:D:i:o:s:S:b:B:F:P:R:")) != -1) {
"1246hpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
switch (ch) {
/* Passed through to ssh(1) */
case '4':
@ -2158,6 +2174,13 @@ main(int argc, char **argv)
case 'D':
sftp_direct = optarg;
break;
case 'l':
limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024,
&errstr);
if (errstr != NULL)
usage();
limit_kbps *= 1024; /* kbps */
break;
case 'r':
global_rflag = 1;
break;
@ -2235,7 +2258,7 @@ main(int argc, char **argv)
}
freeargs(&args);
conn = do_init(in, out, copy_buffer_len, num_requests);
conn = do_init(in, out, copy_buffer_len, num_requests, limit_kbps);
if (conn == NULL)
fatal("Couldn't initialise connection to server");

View File

@ -1,6 +1,4 @@
.\" $OpenBSD: ssh-add.1,v 1.52 2010/03/05 10:28:21 djm Exp $
.\"
.\" -*- nroff -*-
.\" $OpenBSD: ssh-add.1,v 1.55 2010/10/28 18:33:28 jmc Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -37,12 +35,12 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd March 5, 2010
.Dd October 28, 2010
.Dt SSH-ADD 1
.Os
.Sh NAME
.Nm ssh-add
.Nd adds RSA or DSA identities to the authentication agent
.Nd adds private key identities to the authentication agent
.Sh SYNOPSIS
.Nm ssh-add
.Op Fl cDdLlXx
@ -54,11 +52,12 @@
.Fl e Ar pkcs11
.Sh DESCRIPTION
.Nm
adds RSA or DSA identities to the authentication agent,
adds private key identities to the authentication agent,
.Xr ssh-agent 1 .
When run without arguments, it adds the files
.Pa ~/.ssh/id_rsa ,
.Pa ~/.ssh/id_dsa
.Pa ~/.ssh/id_dsa ,
.Pa ~/.ssh/id_ecdsa
and
.Pa ~/.ssh/identity .
After loading a private key,
@ -165,6 +164,8 @@ socket used to communicate with the agent.
Contains the protocol version 1 RSA authentication identity of the user.
.It Pa ~/.ssh/id_dsa
Contains the protocol version 2 DSA authentication identity of the user.
.It Pa ~/.ssh/id_ecdsa
Contains the protocol version 2 ECDSA authentication identity of the user.
.It Pa ~/.ssh/id_rsa
Contains the protocol version 2 RSA authentication identity of the user.
.El
@ -173,7 +174,7 @@ Identity files should not be readable by anyone but the user.
Note that
.Nm
ignores identity files if they are accessible by others.
.Sh DIAGNOSTICS
.Sh EXIT STATUS
Exit status is 0 on success, 1 if the specified command fails,
and 2 if
.Nm

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-add.c,v 1.96 2010/05/14 00:47:22 djm Exp $ */
/* $OpenBSD: ssh-add.c,v 1.100 2010/08/31 12:33:38 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -70,6 +70,9 @@ extern char *__progname;
static char *default_files[] = {
_PATH_SSH_CLIENT_ID_RSA,
_PATH_SSH_CLIENT_ID_DSA,
#ifdef OPENSSL_HAS_ECC
_PATH_SSH_CLIENT_ID_ECDSA,
#endif
_PATH_SSH_CLIENT_IDENTITY,
NULL
};
@ -372,7 +375,7 @@ main(int argc, char **argv)
init_rng();
seed_rng();
SSLeay_add_all_algorithms();
OpenSSL_add_all_algorithms();
/* At first, get a connection to the authentication agent. */
ac = ssh_get_authentication_connection();

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-agent.1,v 1.50 2010/01/17 21:49:09 tedu Exp $
.\" $OpenBSD: ssh-agent.1,v 1.53 2010/11/21 01:01:13 djm Exp $
.\" $FreeBSD$
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -35,7 +35,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd January 17, 2010
.Dd November 21, 2010
.Dt SSH-AGENT 1
.Os
.Sh NAME
@ -43,18 +43,18 @@
.Nd authentication agent
.Sh SYNOPSIS
.Nm ssh-agent
.Op Fl c Li | Fl s
.Op Fl c | s
.Op Fl d
.Op Fl a Ar bind_address
.Op Fl t Ar life
.Op Ar command Op Ar arg ...
.Nm ssh-agent
.Op Fl c Li | Fl s
.Op Fl c | s
.Fl k
.Sh DESCRIPTION
.Nm
is a program to hold private keys used for public key authentication
(RSA, DSA).
(RSA, DSA, ECDSA).
The idea is that
.Nm
is started in the beginning of an X-session or a login session, and
@ -73,7 +73,7 @@ Bind the agent to the
socket
.Ar bind_address .
The default is
.Pa /tmp/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt .
.Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt .
.It Fl c
Generate C-shell commands on
.Dv stdout .
@ -115,7 +115,8 @@ When executed without arguments,
.Xr ssh-add 1
adds the files
.Pa ~/.ssh/id_rsa ,
.Pa ~/.ssh/id_dsa
.Pa ~/.ssh/id_dsa ,
.Pa ~/.ssh/id_ecdsa
and
.Pa ~/.ssh/identity .
If the identity has a passphrase,
@ -188,9 +189,11 @@ line terminates.
Contains the protocol version 1 RSA authentication identity of the user.
.It Pa ~/.ssh/id_dsa
Contains the protocol version 2 DSA authentication identity of the user.
.It Pa ~/.ssh/id_ecdsa
Contains the protocol version 2 ECDSA authentication identity of the user.
.It Pa ~/.ssh/id_rsa
Contains the protocol version 2 RSA authentication identity of the user.
.It Pa /tmp/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt
.It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt
.Ux Ns -domain
sockets used to contain the connection to the authentication agent.
These sockets should only be readable by the owner.

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-agent.c,v 1.166 2010/04/16 01:47:26 djm Exp $ */
/* $OpenBSD: ssh-agent.c,v 1.171 2010/11/21 01:01:13 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -469,6 +469,11 @@ process_add_identity(SocketEntry *e, int version)
int type, success = 0, death = 0, confirm = 0;
char *type_name, *comment;
Key *k = NULL;
#ifdef OPENSSL_HAS_ECC
BIGNUM *exponent;
EC_POINT *q;
char *curve;
#endif
u_char *cert;
u_int len;
@ -491,7 +496,6 @@ process_add_identity(SocketEntry *e, int version)
case 2:
type_name = buffer_get_string(&e->request, NULL);
type = key_type_from_name(type_name);
xfree(type_name);
switch (type) {
case KEY_DSA:
k = key_new_private(type);
@ -510,6 +514,59 @@ process_add_identity(SocketEntry *e, int version)
key_add_private(k);
buffer_get_bignum2(&e->request, k->dsa->priv_key);
break;
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
k = key_new_private(type);
k->ecdsa_nid = key_ecdsa_nid_from_name(type_name);
curve = buffer_get_string(&e->request, NULL);
if (k->ecdsa_nid != key_curve_name_to_nid(curve))
fatal("%s: curve names mismatch", __func__);
xfree(curve);
k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
if (k->ecdsa == NULL)
fatal("%s: EC_KEY_new_by_curve_name failed",
__func__);
q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa));
if (q == NULL)
fatal("%s: BN_new failed", __func__);
if ((exponent = BN_new()) == NULL)
fatal("%s: BN_new failed", __func__);
buffer_get_ecpoint(&e->request,
EC_KEY_get0_group(k->ecdsa), q);
buffer_get_bignum2(&e->request, exponent);
if (EC_KEY_set_public_key(k->ecdsa, q) != 1)
fatal("%s: EC_KEY_set_public_key failed",
__func__);
if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
fatal("%s: EC_KEY_set_private_key failed",
__func__);
if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
EC_KEY_get0_public_key(k->ecdsa)) != 0)
fatal("%s: bad ECDSA public key", __func__);
if (key_ec_validate_private(k->ecdsa) != 0)
fatal("%s: bad ECDSA private key", __func__);
BN_clear_free(exponent);
EC_POINT_free(q);
break;
case KEY_ECDSA_CERT:
cert = buffer_get_string(&e->request, &len);
if ((k = key_from_blob(cert, len)) == NULL)
fatal("Certificate parse failed");
xfree(cert);
key_add_private(k);
if ((exponent = BN_new()) == NULL)
fatal("%s: BN_new failed", __func__);
buffer_get_bignum2(&e->request, exponent);
if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
fatal("%s: EC_KEY_set_private_key failed",
__func__);
if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
EC_KEY_get0_public_key(k->ecdsa)) != 0 ||
key_ec_validate_private(k->ecdsa) != 0)
fatal("%s: bad ECDSA key", __func__);
BN_clear_free(exponent);
break;
#endif /* OPENSSL_HAS_ECC */
case KEY_RSA:
k = key_new_private(type);
buffer_get_bignum2(&e->request, k->rsa->n);
@ -535,9 +592,11 @@ process_add_identity(SocketEntry *e, int version)
buffer_get_bignum2(&e->request, k->rsa->q);
break;
default:
xfree(type_name);
buffer_clear(&e->request);
goto send;
}
xfree(type_name);
break;
}
/* enable blinding */
@ -1094,7 +1153,7 @@ main(int ac, char **av)
prctl(PR_SET_DUMPABLE, 0);
#endif
SSLeay_add_all_algorithms();
OpenSSL_add_all_algorithms();
__progname = ssh_get_progname(av[0]);
init_rng();
@ -1175,7 +1234,7 @@ main(int ac, char **av)
if (agentsocket == NULL) {
/* Create private directory for agent socket */
strlcpy(socket_dir, "/tmp/ssh-XXXXXXXXXX", sizeof socket_dir);
mktemp_proto(socket_dir, sizeof(socket_dir));
if (mkdtemp(socket_dir) == NULL) {
perror("mkdtemp: private socket dir");
exit(1);

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