mirror of git://anongit.mindrot.org/openssh.git
upstream commit
avoid more fatal/exit in the packet.c paths that ssh-keyscan uses; feedback and "looks good" markus@
This commit is contained in:
parent
669aee9943
commit
4509b5d4a4
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: dispatch.c,v 1.24 2015/01/28 22:05:31 djm Exp $ */
|
/* $OpenBSD: dispatch.c,v 1.25 2015/01/30 01:13:33 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -49,9 +49,9 @@ dispatch_protocol_error(int type, u_int32_t seq, void *ctx)
|
||||||
fatal("protocol error");
|
fatal("protocol error");
|
||||||
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
|
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
|
||||||
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
|
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
|
||||||
(r = sshpkt_send(ssh)) != 0)
|
(r = sshpkt_send(ssh)) != 0 ||
|
||||||
fatal("%s: %s", __func__, ssh_err(r));
|
(r = ssh_packet_write_wait(ssh)) != 0)
|
||||||
ssh_packet_write_wait(ssh);
|
sshpkt_fatal(ssh, __func__, r);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
49
opacket.c
49
opacket.c
|
@ -223,6 +223,8 @@ void
|
||||||
packet_set_connection(int fd_in, int fd_out)
|
packet_set_connection(int fd_in, int fd_out)
|
||||||
{
|
{
|
||||||
active_state = ssh_packet_set_connection(active_state, fd_in, fd_out);
|
active_state = ssh_packet_set_connection(active_state, fd_in, fd_out);
|
||||||
|
if (active_state == NULL)
|
||||||
|
fatal("%s: ssh_packet_set_connection failed", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -255,20 +257,8 @@ packet_read_seqnr(u_int32_t *seqnr)
|
||||||
u_char type;
|
u_char type;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = ssh_packet_read_seqnr(active_state, &type, seqnr)) != 0) {
|
if ((r = ssh_packet_read_seqnr(active_state, &type, seqnr)) != 0)
|
||||||
switch (r) {
|
sshpkt_fatal(active_state, __func__, r);
|
||||||
case SSH_ERR_CONN_CLOSED:
|
|
||||||
logit("Connection closed by %.200s",
|
|
||||||
ssh_remote_ipaddr(active_state));
|
|
||||||
cleanup_exit(255);
|
|
||||||
case SSH_ERR_CONN_TIMEOUT:
|
|
||||||
logit("Connection to %.200s timed out while "
|
|
||||||
"waiting to read", ssh_remote_ipaddr(active_state));
|
|
||||||
cleanup_exit(255);
|
|
||||||
default:
|
|
||||||
fatal("%s: %s", __func__, ssh_err(r));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +269,7 @@ packet_read_poll_seqnr(u_int32_t *seqnr)
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = ssh_packet_read_poll_seqnr(active_state, &type, seqnr)))
|
if ((r = ssh_packet_read_poll_seqnr(active_state, &type, seqnr)))
|
||||||
fatal("%s: %s", __func__, ssh_err(r));
|
sshpkt_fatal(active_state, __func__, r);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,5 +286,32 @@ packet_process_incoming(const char *buf, u_int len)
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = ssh_packet_process_incoming(active_state, buf, len)) != 0)
|
if ((r = ssh_packet_process_incoming(active_state, buf, len)) != 0)
|
||||||
fatal("%s: %s", __func__, ssh_err(r));
|
sshpkt_fatal(active_state, __func__, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
packet_write_wait(void)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if ((r = ssh_packet_write_wait(active_state)) != 0)
|
||||||
|
sshpkt_fatal(active_state, __func__, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
packet_write_poll(void)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if ((r = ssh_packet_write_poll(active_state)) != 0)
|
||||||
|
sshpkt_fatal(active_state, __func__, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
packet_read_expect(int expected_type)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if ((r = ssh_packet_read_expect(active_state, expected_type)) != 0)
|
||||||
|
sshpkt_fatal(active_state, __func__, r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,9 @@ void packet_set_connection(int, int);
|
||||||
int packet_read_seqnr(u_int32_t *);
|
int packet_read_seqnr(u_int32_t *);
|
||||||
int packet_read_poll_seqnr(u_int32_t *);
|
int packet_read_poll_seqnr(u_int32_t *);
|
||||||
void packet_process_incoming(const char *buf, u_int len);
|
void packet_process_incoming(const char *buf, u_int len);
|
||||||
|
void packet_write_wait(void);
|
||||||
|
void packet_write_poll(void);
|
||||||
|
void packet_read_expect(int expected_type);
|
||||||
#define packet_set_timeout(timeout, count) \
|
#define packet_set_timeout(timeout, count) \
|
||||||
ssh_packet_set_timeout(active_state, (timeout), (count))
|
ssh_packet_set_timeout(active_state, (timeout), (count))
|
||||||
#define packet_connection_is_on_socket() \
|
#define packet_connection_is_on_socket() \
|
||||||
|
@ -85,8 +88,6 @@ void packet_process_incoming(const char *buf, u_int len);
|
||||||
ssh_packet_send(active_state)
|
ssh_packet_send(active_state)
|
||||||
#define packet_read() \
|
#define packet_read() \
|
||||||
ssh_packet_read(active_state)
|
ssh_packet_read(active_state)
|
||||||
#define packet_read_expect(expected_type) \
|
|
||||||
ssh_packet_read_expect(active_state, (expected_type))
|
|
||||||
#define packet_get_int64() \
|
#define packet_get_int64() \
|
||||||
ssh_packet_get_int64(active_state)
|
ssh_packet_get_int64(active_state)
|
||||||
#define packet_get_bignum(value) \
|
#define packet_get_bignum(value) \
|
||||||
|
@ -105,10 +106,6 @@ void packet_process_incoming(const char *buf, u_int len);
|
||||||
ssh_packet_send_debug(active_state, (fmt), ##args)
|
ssh_packet_send_debug(active_state, (fmt), ##args)
|
||||||
#define packet_disconnect(fmt, args...) \
|
#define packet_disconnect(fmt, args...) \
|
||||||
ssh_packet_disconnect(active_state, (fmt), ##args)
|
ssh_packet_disconnect(active_state, (fmt), ##args)
|
||||||
#define packet_write_poll() \
|
|
||||||
ssh_packet_write_poll(active_state)
|
|
||||||
#define packet_write_wait() \
|
|
||||||
ssh_packet_write_wait(active_state)
|
|
||||||
#define packet_have_data_to_write() \
|
#define packet_have_data_to_write() \
|
||||||
ssh_packet_have_data_to_write(active_state)
|
ssh_packet_have_data_to_write(active_state)
|
||||||
#define packet_not_very_much_data_to_write() \
|
#define packet_not_very_much_data_to_write() \
|
||||||
|
|
220
packet.c
220
packet.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: packet.c,v 1.204 2015/01/28 21:15:47 djm Exp $ */
|
/* $OpenBSD: packet.c,v 1.205 2015/01/30 01:13:33 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -272,20 +272,26 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
|
||||||
const struct sshcipher *none = cipher_by_name("none");
|
const struct sshcipher *none = cipher_by_name("none");
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (none == NULL)
|
if (none == NULL) {
|
||||||
fatal("%s: cannot load cipher 'none'", __func__);
|
error("%s: cannot load cipher 'none'", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (ssh == NULL)
|
if (ssh == NULL)
|
||||||
ssh = ssh_alloc_session_state();
|
ssh = ssh_alloc_session_state();
|
||||||
if (ssh == NULL)
|
if (ssh == NULL) {
|
||||||
fatal("%s: cound not allocate state", __func__);
|
error("%s: cound not allocate state", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
state = ssh->state;
|
state = ssh->state;
|
||||||
state->connection_in = fd_in;
|
state->connection_in = fd_in;
|
||||||
state->connection_out = fd_out;
|
state->connection_out = fd_out;
|
||||||
if ((r = cipher_init(&state->send_context, none,
|
if ((r = cipher_init(&state->send_context, none,
|
||||||
(const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
|
(const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
|
||||||
(r = cipher_init(&state->receive_context, none,
|
(r = cipher_init(&state->receive_context, none,
|
||||||
(const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0)
|
(const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) {
|
||||||
fatal("%s: cipher_init failed: %s", __func__, ssh_err(r));
|
error("%s: cipher_init failed: %s", __func__, ssh_err(r));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL;
|
state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL;
|
||||||
deattack_init(&state->deattack);
|
deattack_init(&state->deattack);
|
||||||
return ssh;
|
return ssh;
|
||||||
|
@ -893,8 +899,8 @@ ssh_packet_send1(struct ssh *ssh)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that the packet is now only buffered in output. It won't be
|
* Note that the packet is now only buffered in output. It won't be
|
||||||
* actually sent until packet_write_wait or packet_write_poll is
|
* actually sent until ssh_packet_write_wait or ssh_packet_write_poll
|
||||||
* called.
|
* is called.
|
||||||
*/
|
*/
|
||||||
r = 0;
|
r = 0;
|
||||||
out:
|
out:
|
||||||
|
@ -1263,8 +1269,12 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
||||||
if (setp == NULL)
|
if (setp == NULL)
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
|
|
||||||
/* Since we are blocking, ensure that all written packets have been sent. */
|
/*
|
||||||
ssh_packet_write_wait(ssh);
|
* Since we are blocking, ensure that all written packets have
|
||||||
|
* been sent.
|
||||||
|
*/
|
||||||
|
if ((r = ssh_packet_write_wait(ssh)) != 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
/* Stay in the loop until we have received a complete packet. */
|
/* Stay in the loop until we have received a complete packet. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -1351,16 +1361,22 @@ ssh_packet_read(struct ssh *ssh)
|
||||||
* that given, and gives a fatal error and exits if there is a mismatch.
|
* that given, and gives a fatal error and exits if there is a mismatch.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
int
|
||||||
ssh_packet_read_expect(struct ssh *ssh, int expected_type)
|
ssh_packet_read_expect(struct ssh *ssh, u_int expected_type)
|
||||||
{
|
{
|
||||||
int type;
|
int r;
|
||||||
|
u_char type;
|
||||||
|
|
||||||
type = ssh_packet_read(ssh);
|
if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0)
|
||||||
if (type != expected_type)
|
return r;
|
||||||
ssh_packet_disconnect(ssh,
|
if (type != expected_type) {
|
||||||
|
if ((r = sshpkt_disconnect(ssh,
|
||||||
"Protocol error: expected packet type %d, got %d",
|
"Protocol error: expected packet type %d, got %d",
|
||||||
expected_type, type);
|
expected_type, type)) != 0)
|
||||||
|
return r;
|
||||||
|
return SSH_ERR_PROTOCOL_ERROR;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checks if a full packet is available in the data received so far via
|
/* Checks if a full packet is available in the data received so far via
|
||||||
|
@ -1377,6 +1393,7 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
|
||||||
{
|
{
|
||||||
struct session_state *state = ssh->state;
|
struct session_state *state = ssh->state;
|
||||||
u_int len, padded_len;
|
u_int len, padded_len;
|
||||||
|
const char *emsg;
|
||||||
const u_char *cp;
|
const u_char *cp;
|
||||||
u_char *p;
|
u_char *p;
|
||||||
u_int checksum, stored_checksum;
|
u_int checksum, stored_checksum;
|
||||||
|
@ -1389,9 +1406,12 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
|
||||||
return 0;
|
return 0;
|
||||||
/* Get length of incoming packet. */
|
/* Get length of incoming packet. */
|
||||||
len = PEEK_U32(sshbuf_ptr(state->input));
|
len = PEEK_U32(sshbuf_ptr(state->input));
|
||||||
if (len < 1 + 2 + 2 || len > 256 * 1024)
|
if (len < 1 + 2 + 2 || len > 256 * 1024) {
|
||||||
ssh_packet_disconnect(ssh, "Bad packet length %u.",
|
if ((r = sshpkt_disconnect(ssh, "Bad packet length %u",
|
||||||
len);
|
len)) != 0)
|
||||||
|
return r;
|
||||||
|
return SSH_ERR_CONN_CORRUPT;
|
||||||
|
}
|
||||||
padded_len = (len + 8) & ~7;
|
padded_len = (len + 8) & ~7;
|
||||||
|
|
||||||
/* Check if the packet has been entirely received. */
|
/* Check if the packet has been entirely received. */
|
||||||
|
@ -1410,19 +1430,27 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
|
||||||
* Ariel Futoransky(futo@core-sdi.com)
|
* Ariel Futoransky(futo@core-sdi.com)
|
||||||
*/
|
*/
|
||||||
if (!state->receive_context.plaintext) {
|
if (!state->receive_context.plaintext) {
|
||||||
|
emsg = NULL;
|
||||||
switch (detect_attack(&state->deattack,
|
switch (detect_attack(&state->deattack,
|
||||||
sshbuf_ptr(state->input), padded_len)) {
|
sshbuf_ptr(state->input), padded_len)) {
|
||||||
case DEATTACK_OK:
|
case DEATTACK_OK:
|
||||||
break;
|
break;
|
||||||
case DEATTACK_DETECTED:
|
case DEATTACK_DETECTED:
|
||||||
ssh_packet_disconnect(ssh,
|
emsg = "crc32 compensation attack detected";
|
||||||
"crc32 compensation attack: network attack detected"
|
break;
|
||||||
);
|
|
||||||
case DEATTACK_DOS_DETECTED:
|
case DEATTACK_DOS_DETECTED:
|
||||||
ssh_packet_disconnect(ssh,
|
emsg = "deattack denial of service detected";
|
||||||
"deattack denial of service detected");
|
break;
|
||||||
default:
|
default:
|
||||||
ssh_packet_disconnect(ssh, "deattack error");
|
emsg = "deattack error";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (emsg != NULL) {
|
||||||
|
error("%s", emsg);
|
||||||
|
if ((r = sshpkt_disconnect(ssh, "%s", emsg)) != 0 ||
|
||||||
|
(r = ssh_packet_write_wait(ssh)) != 0)
|
||||||
|
return r;
|
||||||
|
return SSH_ERR_CONN_CORRUPT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1451,16 +1479,24 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Test check bytes. */
|
/* Test check bytes. */
|
||||||
if (len != sshbuf_len(state->incoming_packet))
|
if (len != sshbuf_len(state->incoming_packet)) {
|
||||||
ssh_packet_disconnect(ssh,
|
error("%s: len %d != sshbuf_len %zd", __func__,
|
||||||
"packet_read_poll1: len %d != sshbuf_len %zd.",
|
|
||||||
len, sshbuf_len(state->incoming_packet));
|
len, sshbuf_len(state->incoming_packet));
|
||||||
|
if ((r = sshpkt_disconnect(ssh, "invalid packet length")) != 0 ||
|
||||||
|
(r = ssh_packet_write_wait(ssh)) != 0)
|
||||||
|
return r;
|
||||||
|
return SSH_ERR_CONN_CORRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
cp = sshbuf_ptr(state->incoming_packet) + len - 4;
|
cp = sshbuf_ptr(state->incoming_packet) + len - 4;
|
||||||
stored_checksum = PEEK_U32(cp);
|
stored_checksum = PEEK_U32(cp);
|
||||||
if (checksum != stored_checksum)
|
if (checksum != stored_checksum) {
|
||||||
ssh_packet_disconnect(ssh,
|
error("Corrupted check bytes on input");
|
||||||
"Corrupted check bytes on input.");
|
if ((r = sshpkt_disconnect(ssh, "connection corrupted")) != 0 ||
|
||||||
|
(r = ssh_packet_write_wait(ssh)) != 0)
|
||||||
|
return r;
|
||||||
|
return SSH_ERR_CONN_CORRUPT;
|
||||||
|
}
|
||||||
if ((r = sshbuf_consume_end(state->incoming_packet, 4)) < 0)
|
if ((r = sshbuf_consume_end(state->incoming_packet, 4)) < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1478,9 +1514,13 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
|
||||||
state->p_read.bytes += padded_len + 4;
|
state->p_read.bytes += padded_len + 4;
|
||||||
if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
|
if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (*typep < SSH_MSG_MIN || *typep > SSH_MSG_MAX)
|
if (*typep < SSH_MSG_MIN || *typep > SSH_MSG_MAX) {
|
||||||
ssh_packet_disconnect(ssh,
|
error("Invalid ssh1 packet type: %d", *typep);
|
||||||
"Invalid ssh1 packet type: %d", *typep);
|
if ((r = sshpkt_disconnect(ssh, "invalid packet type")) != 0 ||
|
||||||
|
(r = ssh_packet_write_wait(ssh)) != 0)
|
||||||
|
return r;
|
||||||
|
return SSH_ERR_PROTOCOL_ERROR;
|
||||||
|
}
|
||||||
r = 0;
|
r = 0;
|
||||||
out:
|
out:
|
||||||
return r;
|
return r;
|
||||||
|
@ -1634,7 +1674,6 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
||||||
if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
|
if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/* XXX now it's safe to use fatal/packet_disconnect */
|
|
||||||
if (seqnr_p != NULL)
|
if (seqnr_p != NULL)
|
||||||
*seqnr_p = state->p_read.seqnr;
|
*seqnr_p = state->p_read.seqnr;
|
||||||
if (++state->p_read.seqnr == 0)
|
if (++state->p_read.seqnr == 0)
|
||||||
|
@ -1648,9 +1687,13 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
||||||
/* get padlen */
|
/* get padlen */
|
||||||
padlen = sshbuf_ptr(state->incoming_packet)[4];
|
padlen = sshbuf_ptr(state->incoming_packet)[4];
|
||||||
DBG(debug("input: padlen %d", padlen));
|
DBG(debug("input: padlen %d", padlen));
|
||||||
if (padlen < 4)
|
if (padlen < 4) {
|
||||||
ssh_packet_disconnect(ssh,
|
if ((r = sshpkt_disconnect(ssh,
|
||||||
"Corrupted padlen %d on input.", padlen);
|
"Corrupted padlen %d on input.", padlen)) != 0 ||
|
||||||
|
(r = ssh_packet_write_wait(ssh)) != 0)
|
||||||
|
return r;
|
||||||
|
return SSH_ERR_CONN_CORRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
/* skip packet size + padlen, discard padding */
|
/* skip packet size + padlen, discard padding */
|
||||||
if ((r = sshbuf_consume(state->incoming_packet, 4 + 1)) != 0 ||
|
if ((r = sshbuf_consume(state->incoming_packet, 4 + 1)) != 0 ||
|
||||||
|
@ -1677,9 +1720,13 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
||||||
*/
|
*/
|
||||||
if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
|
if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN)
|
if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN) {
|
||||||
ssh_packet_disconnect(ssh,
|
if ((r = sshpkt_disconnect(ssh,
|
||||||
"Invalid ssh2 packet type: %d", *typep);
|
"Invalid ssh2 packet type: %d", *typep)) != 0 ||
|
||||||
|
(r = ssh_packet_write_wait(ssh)) != 0)
|
||||||
|
return r;
|
||||||
|
return SSH_ERR_PROTOCOL_ERROR;
|
||||||
|
}
|
||||||
if (*typep == SSH2_MSG_NEWKEYS)
|
if (*typep == SSH2_MSG_NEWKEYS)
|
||||||
r = ssh_set_newkeys(ssh, MODE_IN);
|
r = ssh_set_newkeys(ssh, MODE_IN);
|
||||||
else if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side)
|
else if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side)
|
||||||
|
@ -1816,9 +1863,8 @@ ssh_packet_remaining(struct ssh *ssh)
|
||||||
* message is printed immediately, but only if the client is being executed
|
* message is printed immediately, but only if the client is being executed
|
||||||
* in verbose mode. These messages are primarily intended to ease debugging
|
* in verbose mode. These messages are primarily intended to ease debugging
|
||||||
* authentication problems. The length of the formatted message must not
|
* authentication problems. The length of the formatted message must not
|
||||||
* exceed 1024 bytes. This will automatically call packet_write_wait.
|
* exceed 1024 bytes. This will automatically call ssh_packet_write_wait.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
|
ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
|
||||||
{
|
{
|
||||||
|
@ -1846,7 +1892,29 @@ ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
|
||||||
(r = sshpkt_send(ssh)) != 0)
|
(r = sshpkt_send(ssh)) != 0)
|
||||||
fatal("%s: %s", __func__, ssh_err(r));
|
fatal("%s: %s", __func__, ssh_err(r));
|
||||||
}
|
}
|
||||||
ssh_packet_write_wait(ssh);
|
if ((r = ssh_packet_write_wait(ssh)) != 0)
|
||||||
|
fatal("%s: %s", __func__, ssh_err(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pretty-print connection-terminating errors and exit.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
|
||||||
|
{
|
||||||
|
switch (r) {
|
||||||
|
case SSH_ERR_CONN_CLOSED:
|
||||||
|
logit("Connection closed by %.200s", ssh_remote_ipaddr(ssh));
|
||||||
|
cleanup_exit(255);
|
||||||
|
case SSH_ERR_CONN_TIMEOUT:
|
||||||
|
logit("Connection to %.200s timed out while "
|
||||||
|
"waiting to write", ssh_remote_ipaddr(ssh));
|
||||||
|
cleanup_exit(255);
|
||||||
|
default:
|
||||||
|
fatal("%s%sConnection to %.200s: %s",
|
||||||
|
tag != NULL ? tag : "", tag != NULL ? ": " : "",
|
||||||
|
ssh_remote_ipaddr(ssh), ssh_err(r));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1855,7 +1923,6 @@ ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
|
||||||
* should not contain a newline. The length of the formatted message must
|
* should not contain a newline. The length of the formatted message must
|
||||||
* not exceed 1024 bytes.
|
* not exceed 1024 bytes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
|
ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
|
||||||
{
|
{
|
||||||
|
@ -1879,30 +1946,26 @@ ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
|
||||||
/* Display the error locally */
|
/* Display the error locally */
|
||||||
logit("Disconnecting: %.100s", buf);
|
logit("Disconnecting: %.100s", buf);
|
||||||
|
|
||||||
/* Send the disconnect message to the other side, and wait for it to get sent. */
|
/*
|
||||||
if (compat20) {
|
* Send the disconnect message to the other side, and wait
|
||||||
if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
|
* for it to get sent.
|
||||||
(r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
|
*/
|
||||||
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
|
if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0)
|
||||||
(r = sshpkt_put_cstring(ssh, "")) != 0 ||
|
sshpkt_fatal(ssh, __func__, r);
|
||||||
(r = sshpkt_send(ssh)) != 0)
|
|
||||||
fatal("%s: %s", __func__, ssh_err(r));
|
if ((r = ssh_packet_write_wait(ssh)) != 0)
|
||||||
} else {
|
sshpkt_fatal(ssh, __func__, r);
|
||||||
if ((r = sshpkt_start(ssh, SSH_MSG_DISCONNECT)) != 0 ||
|
|
||||||
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
|
|
||||||
(r = sshpkt_send(ssh)) != 0)
|
|
||||||
fatal("%s: %s", __func__, ssh_err(r));
|
|
||||||
}
|
|
||||||
ssh_packet_write_wait(ssh);
|
|
||||||
|
|
||||||
/* Close the connection. */
|
/* Close the connection. */
|
||||||
ssh_packet_close(ssh);
|
ssh_packet_close(ssh);
|
||||||
cleanup_exit(255);
|
cleanup_exit(255);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checks if there is any buffered output, and tries to write some of the output. */
|
/*
|
||||||
|
* Checks if there is any buffered output, and tries to write some of
|
||||||
void
|
* the output.
|
||||||
|
*/
|
||||||
|
int
|
||||||
ssh_packet_write_poll(struct ssh *ssh)
|
ssh_packet_write_poll(struct ssh *ssh)
|
||||||
{
|
{
|
||||||
struct session_state *state = ssh->state;
|
struct session_state *state = ssh->state;
|
||||||
|
@ -1916,33 +1979,33 @@ ssh_packet_write_poll(struct ssh *ssh)
|
||||||
if (len == -1) {
|
if (len == -1) {
|
||||||
if (errno == EINTR || errno == EAGAIN ||
|
if (errno == EINTR || errno == EAGAIN ||
|
||||||
errno == EWOULDBLOCK)
|
errno == EWOULDBLOCK)
|
||||||
return;
|
return 0;
|
||||||
fatal("Write failed: %.100s", strerror(errno));
|
return SSH_ERR_SYSTEM_ERROR;
|
||||||
}
|
}
|
||||||
if (len == 0 && !cont)
|
if (len == 0 && !cont)
|
||||||
fatal("Write connection closed");
|
return SSH_ERR_CONN_CLOSED;
|
||||||
if ((r = sshbuf_consume(state->output, len)) != 0)
|
if ((r = sshbuf_consume(state->output, len)) != 0)
|
||||||
fatal("%s: %s", __func__, ssh_err(r));
|
return r;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calls packet_write_poll repeatedly until all pending output data has been
|
* Calls packet_write_poll repeatedly until all pending output data has been
|
||||||
* written.
|
* written.
|
||||||
*/
|
*/
|
||||||
|
int
|
||||||
void
|
|
||||||
ssh_packet_write_wait(struct ssh *ssh)
|
ssh_packet_write_wait(struct ssh *ssh)
|
||||||
{
|
{
|
||||||
fd_set *setp;
|
fd_set *setp;
|
||||||
int ret, ms_remain = 0;
|
int ret, r, ms_remain = 0;
|
||||||
struct timeval start, timeout, *timeoutp = NULL;
|
struct timeval start, timeout, *timeoutp = NULL;
|
||||||
struct session_state *state = ssh->state;
|
struct session_state *state = ssh->state;
|
||||||
|
|
||||||
setp = (fd_set *)calloc(howmany(state->connection_out + 1,
|
setp = (fd_set *)calloc(howmany(state->connection_out + 1,
|
||||||
NFDBITS), sizeof(fd_mask));
|
NFDBITS), sizeof(fd_mask));
|
||||||
if (setp == NULL)
|
if (setp == NULL)
|
||||||
fatal("%s: calloc failed", __func__);
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
ssh_packet_write_poll(ssh);
|
ssh_packet_write_poll(ssh);
|
||||||
while (ssh_packet_have_data_to_write(ssh)) {
|
while (ssh_packet_have_data_to_write(ssh)) {
|
||||||
memset(setp, 0, howmany(state->connection_out + 1,
|
memset(setp, 0, howmany(state->connection_out + 1,
|
||||||
|
@ -1973,13 +2036,16 @@ ssh_packet_write_wait(struct ssh *ssh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
logit("Connection to %.200s timed out while "
|
free(setp);
|
||||||
"waiting to write", ssh_remote_ipaddr(ssh));
|
return SSH_ERR_CONN_TIMEOUT;
|
||||||
cleanup_exit(255);
|
}
|
||||||
|
if ((r = ssh_packet_write_poll(ssh)) != 0) {
|
||||||
|
free(setp);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
ssh_packet_write_poll(ssh);
|
|
||||||
}
|
}
|
||||||
free(setp);
|
free(setp);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if there is buffered data to write to the connection. */
|
/* Returns true if there is buffered data to write to the connection. */
|
||||||
|
|
12
packet.h
12
packet.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: packet.h,v 1.65 2015/01/28 21:15:47 djm Exp $ */
|
/* $OpenBSD: packet.h,v 1.66 2015/01/30 01:13:33 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -90,7 +90,7 @@ int ssh_packet_send2_wrapped(struct ssh *);
|
||||||
int ssh_packet_send2(struct ssh *);
|
int ssh_packet_send2(struct ssh *);
|
||||||
|
|
||||||
int ssh_packet_read(struct ssh *);
|
int ssh_packet_read(struct ssh *);
|
||||||
void ssh_packet_read_expect(struct ssh *, int type);
|
int ssh_packet_read_expect(struct ssh *, u_int type);
|
||||||
int ssh_packet_read_poll(struct ssh *);
|
int ssh_packet_read_poll(struct ssh *);
|
||||||
int ssh_packet_read_poll1(struct ssh *, u_char *);
|
int ssh_packet_read_poll1(struct ssh *, u_char *);
|
||||||
int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p);
|
int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p);
|
||||||
|
@ -112,8 +112,8 @@ typedef void (ssh_packet_comp_free_func)(void *, void *);
|
||||||
void ssh_packet_set_compress_hooks(struct ssh *, void *,
|
void ssh_packet_set_compress_hooks(struct ssh *, void *,
|
||||||
ssh_packet_comp_alloc_func *, ssh_packet_comp_free_func *);
|
ssh_packet_comp_alloc_func *, ssh_packet_comp_free_func *);
|
||||||
|
|
||||||
void ssh_packet_write_poll(struct ssh *);
|
int ssh_packet_write_poll(struct ssh *);
|
||||||
void ssh_packet_write_wait(struct ssh *);
|
int ssh_packet_write_wait(struct ssh *);
|
||||||
int ssh_packet_have_data_to_write(struct ssh *);
|
int ssh_packet_have_data_to_write(struct ssh *);
|
||||||
int ssh_packet_not_very_much_data_to_write(struct ssh *);
|
int ssh_packet_not_very_much_data_to_write(struct ssh *);
|
||||||
|
|
||||||
|
@ -148,8 +148,10 @@ void *ssh_packet_get_output(struct ssh *);
|
||||||
/* new API */
|
/* new API */
|
||||||
int sshpkt_start(struct ssh *ssh, u_char type);
|
int sshpkt_start(struct ssh *ssh, u_char type);
|
||||||
int sshpkt_send(struct ssh *ssh);
|
int sshpkt_send(struct ssh *ssh);
|
||||||
int sshpkt_disconnect(struct ssh *, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
|
int sshpkt_disconnect(struct ssh *, const char *fmt, ...)
|
||||||
|
__attribute__((format(printf, 2, 3)));
|
||||||
int sshpkt_add_padding(struct ssh *, u_char);
|
int sshpkt_add_padding(struct ssh *, u_char);
|
||||||
|
void sshpkt_fatal(struct ssh *ssh, const char *tag, int r);
|
||||||
|
|
||||||
int sshpkt_put(struct ssh *ssh, const void *v, size_t len);
|
int sshpkt_put(struct ssh *ssh, const void *v, size_t len);
|
||||||
int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b);
|
int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh-keyscan.c,v 1.97 2015/01/28 21:15:47 djm Exp $ */
|
/* $OpenBSD: ssh-keyscan.c,v 1.98 2015/01/30 01:13:33 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
|
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
|
||||||
*
|
*
|
||||||
|
@ -466,7 +466,8 @@ congreet(int s)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
c->c_ssh = ssh_packet_set_connection(NULL, s, s);
|
if ((c->c_ssh = ssh_packet_set_connection(NULL, s, s)) == NULL)
|
||||||
|
fatal("ssh_packet_set_connection failed");
|
||||||
ssh_set_app_data(c->c_ssh, c); /* back link */
|
ssh_set_app_data(c->c_ssh, c); /* back link */
|
||||||
if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
|
if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
|
||||||
&remote_major, &remote_minor, remote_version) == 3)
|
&remote_major, &remote_minor, remote_version) == 3)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh_api.c,v 1.2 2015/01/26 06:10:03 djm Exp $ */
|
/* $OpenBSD: ssh_api.c,v 1.3 2015/01/30 01:13:33 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 Markus Friedl. All rights reserved.
|
* Copyright (c) 2012 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -85,7 +85,8 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
|
||||||
called = 1;
|
called = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh = ssh_packet_set_connection(NULL, -1, -1);
|
if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL)
|
||||||
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
if (is_server)
|
if (is_server)
|
||||||
ssh_packet_set_server(ssh);
|
ssh_packet_set_server(ssh);
|
||||||
|
|
||||||
|
|
6
ssherr.c
6
ssherr.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssherr.c,v 1.2 2015/01/28 21:15:47 djm Exp $ */
|
/* $OpenBSD: ssherr.c,v 1.3 2015/01/30 01:13:33 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 Damien Miller
|
* Copyright (c) 2011 Damien Miller
|
||||||
*
|
*
|
||||||
|
@ -129,6 +129,10 @@ ssh_err(int n)
|
||||||
return "Connection closed";
|
return "Connection closed";
|
||||||
case SSH_ERR_CONN_TIMEOUT:
|
case SSH_ERR_CONN_TIMEOUT:
|
||||||
return "Connection timed out";
|
return "Connection timed out";
|
||||||
|
case SSH_ERR_CONN_CORRUPT:
|
||||||
|
return "Connection corrupted";
|
||||||
|
case SSH_ERR_PROTOCOL_ERROR:
|
||||||
|
return "Protocol error";
|
||||||
default:
|
default:
|
||||||
return "unknown error";
|
return "unknown error";
|
||||||
}
|
}
|
||||||
|
|
4
ssherr.h
4
ssherr.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssherr.h,v 1.2 2015/01/28 21:15:47 djm Exp $ */
|
/* $OpenBSD: ssherr.h,v 1.3 2015/01/30 01:13:33 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 Damien Miller
|
* Copyright (c) 2011 Damien Miller
|
||||||
*
|
*
|
||||||
|
@ -75,6 +75,8 @@
|
||||||
#define SSH_ERR_KEY_REVOKED -51
|
#define SSH_ERR_KEY_REVOKED -51
|
||||||
#define SSH_ERR_CONN_CLOSED -52
|
#define SSH_ERR_CONN_CLOSED -52
|
||||||
#define SSH_ERR_CONN_TIMEOUT -53
|
#define SSH_ERR_CONN_TIMEOUT -53
|
||||||
|
#define SSH_ERR_CONN_CORRUPT -54
|
||||||
|
#define SSH_ERR_PROTOCOL_ERROR -55
|
||||||
|
|
||||||
/* Translate a numeric error code to a human-readable error string */
|
/* Translate a numeric error code to a human-readable error string */
|
||||||
const char *ssh_err(int n);
|
const char *ssh_err(int n);
|
||||||
|
|
Loading…
Reference in New Issue