version 1.30, 2018/01/15 05:04:58 |
version 1.30.2.4, 2018/10/20 06:58:16 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
/* $OpenBSD: packet.c,v 1.264 2017/09/12 06:32:07 djm Exp $ */ |
/* $OpenBSD: packet.c,v 1.277 2018/07/16 03:09:13 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 |
Line 62 __RCSID("$NetBSD$"); |
|
Line 63 __RCSID("$NetBSD$"); |
|
|
|
#include <zlib.h> |
#include <zlib.h> |
|
|
#include "buffer.h" /* typedefs XXX */ |
|
#include "key.h" /* typedefs XXX */ |
|
|
|
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "crc32.h" |
#include "crc32.h" |
#include "compat.h" |
#include "compat.h" |
Line 146 struct session_state { |
|
Line 144 struct session_state { |
|
int compression_in_failures; |
int compression_in_failures; |
int compression_out_failures; |
int compression_out_failures; |
|
|
/* |
|
* Flag indicating whether packet compression/decompression is |
|
* enabled. |
|
*/ |
|
int packet_compression; |
|
|
|
/* default maximum packet size */ |
/* default maximum packet size */ |
u_int max_packet_size; |
u_int max_packet_size; |
|
|
Line 417 ssh_packet_start_discard(struct ssh *ssh |
|
Line 409 ssh_packet_start_discard(struct ssh *ssh |
|
int |
int |
ssh_packet_connection_is_on_socket(struct ssh *ssh) |
ssh_packet_connection_is_on_socket(struct ssh *ssh) |
{ |
{ |
struct session_state *state = ssh->state; |
struct session_state *state; |
struct sockaddr_storage from, to; |
struct sockaddr_storage from, to; |
socklen_t fromlen, tolen; |
socklen_t fromlen, tolen; |
|
|
if (state->connection_in == -1 || state->connection_out == -1) |
if (ssh == NULL || ssh->state == NULL) |
return 0; |
return 0; |
|
|
|
state = ssh->state; |
|
if (state->connection_in == -1 || state->connection_out == -1) |
|
return 0; |
/* filedescriptors in and out are the same, so it's a socket */ |
/* filedescriptors in and out are the same, so it's a socket */ |
if (state->connection_in == state->connection_out) |
if (state->connection_in == state->connection_out) |
return 1; |
return 1; |
Line 502 ssh_packet_get_connection_out(struct ssh |
|
Line 497 ssh_packet_get_connection_out(struct ssh |
|
const char * |
const char * |
ssh_remote_ipaddr(struct ssh *ssh) |
ssh_remote_ipaddr(struct ssh *ssh) |
{ |
{ |
const int sock = ssh->state->connection_in; |
int sock; |
|
|
/* Check whether we have cached the ipaddr. */ |
/* Check whether we have cached the ipaddr. */ |
if (ssh->remote_ipaddr == NULL) { |
if (ssh->remote_ipaddr == NULL) { |
if (ssh_packet_connection_is_on_socket(ssh)) { |
if (ssh_packet_connection_is_on_socket(ssh)) { |
|
sock = ssh->state->connection_in; |
ssh->remote_ipaddr = get_peer_ipaddr(sock); |
ssh->remote_ipaddr = get_peer_ipaddr(sock); |
ssh->remote_port = get_peer_port(sock); |
ssh->remote_port = get_peer_port(sock); |
ssh->local_ipaddr = get_local_ipaddr(sock); |
ssh->local_ipaddr = get_local_ipaddr(sock); |
Line 551 ssh_local_port(struct ssh *ssh) |
|
Line 547 ssh_local_port(struct ssh *ssh) |
|
return ssh->local_port; |
return ssh->local_port; |
} |
} |
|
|
|
/* Returns the routing domain of the input socket, or NULL if unavailable */ |
|
const char * |
|
ssh_packet_rdomain_in(struct ssh *ssh) |
|
{ |
|
if (ssh->rdomain_in != NULL) |
|
return ssh->rdomain_in; |
|
if (!ssh_packet_connection_is_on_socket(ssh)) |
|
return NULL; |
|
ssh->rdomain_in = get_rdomain(ssh->state->connection_in); |
|
return ssh->rdomain_in; |
|
} |
|
|
/* Closes the connection and clears and frees internal data structures. */ |
/* Closes the connection and clears and frees internal data structures. */ |
|
|
static void |
static void |
Line 609 ssh_packet_close_internal(struct ssh *ss |
|
Line 617 ssh_packet_close_internal(struct ssh *ss |
|
cipher_free(state->receive_context); |
cipher_free(state->receive_context); |
state->send_context = state->receive_context = NULL; |
state->send_context = state->receive_context = NULL; |
if (do_close) { |
if (do_close) { |
|
free(ssh->local_ipaddr); |
|
ssh->local_ipaddr = NULL; |
free(ssh->remote_ipaddr); |
free(ssh->remote_ipaddr); |
ssh->remote_ipaddr = NULL; |
ssh->remote_ipaddr = NULL; |
free(ssh->state); |
free(ssh->state); |
Line 695 start_compression_in(struct ssh *ssh) |
|
Line 705 start_compression_in(struct ssh *ssh) |
|
return 0; |
return 0; |
} |
} |
|
|
int |
|
ssh_packet_start_compression(struct ssh *ssh, int level) |
|
{ |
|
int r; |
|
|
|
if (ssh->state->packet_compression) |
|
return SSH_ERR_INTERNAL_ERROR; |
|
ssh->state->packet_compression = 1; |
|
if ((r = ssh_packet_init_compression(ssh)) != 0 || |
|
(r = start_compression_in(ssh)) != 0 || |
|
(r = start_compression_out(ssh, level)) != 0) |
|
return r; |
|
return 0; |
|
} |
|
|
|
/* XXX remove need for separate compression buffer */ |
/* XXX remove need for separate compression buffer */ |
static int |
static int |
compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) |
compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) |
Line 1322 ssh_packet_read_seqnr(struct ssh *ssh, u |
|
Line 1317 ssh_packet_read_seqnr(struct ssh *ssh, u |
|
for (;;) { |
for (;;) { |
if (state->packet_timeout_ms != -1) { |
if (state->packet_timeout_ms != -1) { |
ms_to_timeval(&timeout, ms_remain); |
ms_to_timeval(&timeout, ms_remain); |
gettimeofday(&start, NULL); |
monotime_tv(&start); |
} |
} |
if ((r = select(state->connection_in + 1, setp, |
if ((r = select(state->connection_in + 1, setp, |
NULL, NULL, timeoutp)) >= 0) |
NULL, NULL, timeoutp)) >= 0) |
break; |
break; |
if (errno != EAGAIN && errno != EINTR) |
if (errno != EAGAIN && errno != EINTR) { |
break; |
r = SSH_ERR_SYSTEM_ERROR; |
|
goto out; |
|
} |
if (state->packet_timeout_ms == -1) |
if (state->packet_timeout_ms == -1) |
continue; |
continue; |
ms_subtract_diff(&start, &ms_remain); |
ms_subtract_diff(&start, &ms_remain); |
Line 1775 ssh_packet_send_debug(struct ssh *ssh, c |
|
Line 1772 ssh_packet_send_debug(struct ssh *ssh, c |
|
vsnprintf(buf, sizeof(buf), fmt, args); |
vsnprintf(buf, sizeof(buf), fmt, args); |
va_end(args); |
va_end(args); |
|
|
|
debug3("sending debug message: %s", buf); |
|
|
if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 || |
if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 || |
(r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */ |
(r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */ |
(r = sshpkt_put_cstring(ssh, buf)) != 0 || |
(r = sshpkt_put_cstring(ssh, buf)) != 0 || |
Line 1785 ssh_packet_send_debug(struct ssh *ssh, c |
|
Line 1784 ssh_packet_send_debug(struct ssh *ssh, c |
|
sshpkt_fatal(ssh, __func__, r); |
sshpkt_fatal(ssh, __func__, r); |
} |
} |
|
|
static void |
void |
fmt_connection_id(struct ssh *ssh, char *s, size_t l) |
sshpkt_fmt_connection_id(struct ssh *ssh, char *s, size_t l) |
{ |
{ |
snprintf(s, l, "%.200s%s%s port %d", |
snprintf(s, l, "%.200s%s%s port %d", |
ssh->log_preamble ? ssh->log_preamble : "", |
ssh->log_preamble ? ssh->log_preamble : "", |
Line 1802 sshpkt_fatal(struct ssh *ssh, const char |
|
Line 1801 sshpkt_fatal(struct ssh *ssh, const char |
|
{ |
{ |
char remote_id[512]; |
char remote_id[512]; |
|
|
fmt_connection_id(ssh, remote_id, sizeof(remote_id)); |
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); |
|
|
switch (r) { |
switch (r) { |
case SSH_ERR_CONN_CLOSED: |
case SSH_ERR_CONN_CLOSED: |
Line 1864 ssh_packet_disconnect(struct ssh *ssh, c |
|
Line 1863 ssh_packet_disconnect(struct ssh *ssh, c |
|
* Format the message. Note that the caller must make sure the |
* Format the message. Note that the caller must make sure the |
* message is of limited size. |
* message is of limited size. |
*/ |
*/ |
fmt_connection_id(ssh, remote_id, sizeof(remote_id)); |
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); |
va_start(args, fmt); |
va_start(args, fmt); |
vsnprintf(buf, sizeof(buf), fmt, args); |
vsnprintf(buf, sizeof(buf), fmt, args); |
va_end(args); |
va_end(args); |
Line 1884 ssh_packet_disconnect(struct ssh *ssh, c |
|
Line 1883 ssh_packet_disconnect(struct ssh *ssh, c |
|
|
|
/* Close the connection. */ |
/* Close the connection. */ |
ssh_packet_close(ssh); |
ssh_packet_close(ssh); |
cleanup_exit(255); |
cleanup_exit(254); |
} |
} |
|
|
/* |
/* |
Line 1950 ssh_packet_write_wait(struct ssh *ssh) |
|
Line 1949 ssh_packet_write_wait(struct ssh *ssh) |
|
for (;;) { |
for (;;) { |
if (state->packet_timeout_ms != -1) { |
if (state->packet_timeout_ms != -1) { |
ms_to_timeval(&timeout, ms_remain); |
ms_to_timeval(&timeout, ms_remain); |
gettimeofday(&start, NULL); |
monotime_tv(&start); |
} |
} |
if ((ret = select(state->connection_out + 1, |
if ((ret = select(state->connection_out + 1, |
NULL, setp, NULL, timeoutp)) >= 0) |
NULL, setp, NULL, timeoutp)) >= 0) |
Line 2158 kex_to_blob(struct sshbuf *m, struct kex |
|
Line 2157 kex_to_blob(struct sshbuf *m, struct kex |
|
if ((r = sshbuf_put_string(m, kex->session_id, |
if ((r = sshbuf_put_string(m, kex->session_id, |
kex->session_id_len)) != 0 || |
kex->session_id_len)) != 0 || |
(r = sshbuf_put_u32(m, kex->we_need)) != 0 || |
(r = sshbuf_put_u32(m, kex->we_need)) != 0 || |
|
(r = sshbuf_put_cstring(m, kex->hostkey_alg)) != 0 || |
(r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 || |
(r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 || |
|
(r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 || |
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 || |
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 || |
(r = sshbuf_put_stringb(m, kex->my)) != 0 || |
(r = sshbuf_put_stringb(m, kex->my)) != 0 || |
(r = sshbuf_put_stringb(m, kex->peer)) != 0 || |
(r = sshbuf_put_stringb(m, kex->peer)) != 0 || |
Line 2322 kex_from_blob(struct sshbuf *m, struct k |
|
Line 2323 kex_from_blob(struct sshbuf *m, struct k |
|
} |
} |
if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || |
if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || |
(r = sshbuf_get_u32(m, &kex->we_need)) != 0 || |
(r = sshbuf_get_u32(m, &kex->we_need)) != 0 || |
|
(r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 || |
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 || |
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 || |
|
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 || |
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || |
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || |
(r = sshbuf_get_stringb(m, kex->my)) != 0 || |
(r = sshbuf_get_stringb(m, kex->my)) != 0 || |
(r = sshbuf_get_stringb(m, kex->peer)) != 0 || |
(r = sshbuf_get_stringb(m, kex->peer)) != 0 || |