summaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2016-08-06 10:49:59 +0100
committerColin Watson <cjwatson@debian.org>2016-08-07 12:18:58 +0100
commit477bb7636238c106f8cd7c868a8c0c5eabcfb3db (patch)
tree601176af2ecf358c36b766776a86845ad7a3cd6f /packet.c
parent747fac2de0d889183f67f6900194c0462c558544 (diff)
parent4c914ccd85bbf391c4dc61b85e3c178fef465e3f (diff)
New upstream release (7.3p1).
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c142
1 files changed, 92 insertions, 50 deletions
diff --git a/packet.c b/packet.c
index f406c0755..d6dad2da6 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.229 2016/02/17 22:20:14 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.234 2016/07/18 11:35:33 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -52,6 +52,7 @@
52#include <arpa/inet.h> 52#include <arpa/inet.h>
53 53
54#include <errno.h> 54#include <errno.h>
55#include <netdb.h>
55#include <stdarg.h> 56#include <stdarg.h>
56#include <stdio.h> 57#include <stdio.h>
57#include <stdlib.h> 58#include <stdlib.h>
@@ -195,6 +196,7 @@ struct session_state {
195 196
196 /* XXX discard incoming data after MAC error */ 197 /* XXX discard incoming data after MAC error */
197 u_int packet_discard; 198 u_int packet_discard;
199 size_t packet_discard_mac_already;
198 struct sshmac *packet_discard_mac; 200 struct sshmac *packet_discard_mac;
199 201
200 /* Used in packet_read_poll2() */ 202 /* Used in packet_read_poll2() */
@@ -296,7 +298,7 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
296 (r = cipher_init(&state->receive_context, none, 298 (r = cipher_init(&state->receive_context, none,
297 (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) { 299 (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) {
298 error("%s: cipher_init failed: %s", __func__, ssh_err(r)); 300 error("%s: cipher_init failed: %s", __func__, ssh_err(r));
299 free(ssh); 301 free(ssh); /* XXX need ssh_free_session_state? */
300 return NULL; 302 return NULL;
301 } 303 }
302 state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL; 304 state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL;
@@ -332,16 +334,18 @@ ssh_packet_stop_discard(struct ssh *ssh)
332 334
333 if (state->packet_discard_mac) { 335 if (state->packet_discard_mac) {
334 char buf[1024]; 336 char buf[1024];
337 size_t dlen = PACKET_MAX_SIZE;
335 338
339 if (dlen > state->packet_discard_mac_already)
340 dlen -= state->packet_discard_mac_already;
336 memset(buf, 'a', sizeof(buf)); 341 memset(buf, 'a', sizeof(buf));
337 while (sshbuf_len(state->incoming_packet) < 342 while (sshbuf_len(state->incoming_packet) < dlen)
338 PACKET_MAX_SIZE)
339 if ((r = sshbuf_put(state->incoming_packet, buf, 343 if ((r = sshbuf_put(state->incoming_packet, buf,
340 sizeof(buf))) != 0) 344 sizeof(buf))) != 0)
341 return r; 345 return r;
342 (void) mac_compute(state->packet_discard_mac, 346 (void) mac_compute(state->packet_discard_mac,
343 state->p_read.seqnr, 347 state->p_read.seqnr,
344 sshbuf_ptr(state->incoming_packet), PACKET_MAX_SIZE, 348 sshbuf_ptr(state->incoming_packet), dlen,
345 NULL, 0); 349 NULL, 0);
346 } 350 }
347 logit("Finished discarding for %.200s port %d", 351 logit("Finished discarding for %.200s port %d",
@@ -351,7 +355,7 @@ ssh_packet_stop_discard(struct ssh *ssh)
351 355
352static int 356static int
353ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc, 357ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc,
354 struct sshmac *mac, u_int packet_length, u_int discard) 358 struct sshmac *mac, size_t mac_already, u_int discard)
355{ 359{
356 struct session_state *state = ssh->state; 360 struct session_state *state = ssh->state;
357 int r; 361 int r;
@@ -361,11 +365,16 @@ ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc,
361 return r; 365 return r;
362 return SSH_ERR_MAC_INVALID; 366 return SSH_ERR_MAC_INVALID;
363 } 367 }
364 if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled) 368 /*
369 * Record number of bytes over which the mac has already
370 * been computed in order to minimize timing attacks.
371 */
372 if (mac && mac->enabled) {
365 state->packet_discard_mac = mac; 373 state->packet_discard_mac = mac;
366 if (sshbuf_len(state->input) >= discard && 374 state->packet_discard_mac_already = mac_already;
367 (r = ssh_packet_stop_discard(ssh)) != 0) 375 }
368 return r; 376 if (sshbuf_len(state->input) >= discard)
377 return ssh_packet_stop_discard(ssh);
369 state->packet_discard = discard - sshbuf_len(state->input); 378 state->packet_discard = discard - sshbuf_len(state->input);
370 return 0; 379 return 0;
371} 380}
@@ -379,6 +388,9 @@ ssh_packet_connection_is_on_socket(struct ssh *ssh)
379 struct sockaddr_storage from, to; 388 struct sockaddr_storage from, to;
380 socklen_t fromlen, tolen; 389 socklen_t fromlen, tolen;
381 390
391 if (state->connection_in == -1 || state->connection_out == -1)
392 return 0;
393
382 /* filedescriptors in and out are the same, so it's a socket */ 394 /* filedescriptors in and out are the same, so it's a socket */
383 if (state->connection_in == state->connection_out) 395 if (state->connection_in == state->connection_out)
384 return 1; 396 return 1;
@@ -468,10 +480,14 @@ ssh_remote_ipaddr(struct ssh *ssh)
468 if (ssh->remote_ipaddr == NULL) { 480 if (ssh->remote_ipaddr == NULL) {
469 if (ssh_packet_connection_is_on_socket(ssh)) { 481 if (ssh_packet_connection_is_on_socket(ssh)) {
470 ssh->remote_ipaddr = get_peer_ipaddr(sock); 482 ssh->remote_ipaddr = get_peer_ipaddr(sock);
471 ssh->remote_port = get_sock_port(sock, 0); 483 ssh->remote_port = get_peer_port(sock);
484 ssh->local_ipaddr = get_local_ipaddr(sock);
485 ssh->local_port = get_local_port(sock);
472 } else { 486 } else {
473 ssh->remote_ipaddr = strdup("UNKNOWN"); 487 ssh->remote_ipaddr = strdup("UNKNOWN");
474 ssh->remote_port = 0; 488 ssh->remote_port = 65535;
489 ssh->local_ipaddr = strdup("UNKNOWN");
490 ssh->local_port = 65535;
475 } 491 }
476 } 492 }
477 return ssh->remote_ipaddr; 493 return ssh->remote_ipaddr;
@@ -486,6 +502,27 @@ ssh_remote_port(struct ssh *ssh)
486 return ssh->remote_port; 502 return ssh->remote_port;
487} 503}
488 504
505/*
506 * Returns the IP-address of the local host as a string. The returned
507 * string must not be freed.
508 */
509
510const char *
511ssh_local_ipaddr(struct ssh *ssh)
512{
513 (void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
514 return ssh->local_ipaddr;
515}
516
517/* Returns the port number of the local host. */
518
519int
520ssh_local_port(struct ssh *ssh)
521{
522 (void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
523 return ssh->local_port;
524}
525
489/* Closes the connection and clears and frees internal data structures. */ 526/* Closes the connection and clears and frees internal data structures. */
490 527
491void 528void
@@ -1142,7 +1179,7 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
1142{ 1179{
1143 struct session_state *state = ssh->state; 1180 struct session_state *state = ssh->state;
1144 u_char type, *cp, macbuf[SSH_DIGEST_MAX_LENGTH]; 1181 u_char type, *cp, macbuf[SSH_DIGEST_MAX_LENGTH];
1145 u_char padlen, pad = 0; 1182 u_char tmp, padlen, pad = 0;
1146 u_int authlen = 0, aadlen = 0; 1183 u_int authlen = 0, aadlen = 0;
1147 u_int len; 1184 u_int len;
1148 struct sshenc *enc = NULL; 1185 struct sshenc *enc = NULL;
@@ -1200,14 +1237,24 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
1200 if (padlen < 4) 1237 if (padlen < 4)
1201 padlen += block_size; 1238 padlen += block_size;
1202 if (state->extra_pad) { 1239 if (state->extra_pad) {
1203 /* will wrap if extra_pad+padlen > 255 */ 1240 tmp = state->extra_pad;
1204 state->extra_pad = 1241 state->extra_pad =
1205 roundup(state->extra_pad, block_size); 1242 roundup(state->extra_pad, block_size);
1206 pad = state->extra_pad - 1243 /* check if roundup overflowed */
1207 ((len + padlen) % state->extra_pad); 1244 if (state->extra_pad < tmp)
1245 return SSH_ERR_INVALID_ARGUMENT;
1246 tmp = (len + padlen) % state->extra_pad;
1247 /* Check whether pad calculation below will underflow */
1248 if (tmp > state->extra_pad)
1249 return SSH_ERR_INVALID_ARGUMENT;
1250 pad = state->extra_pad - tmp;
1208 DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)", 1251 DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)",
1209 __func__, pad, len, padlen, state->extra_pad)); 1252 __func__, pad, len, padlen, state->extra_pad));
1253 tmp = padlen;
1210 padlen += pad; 1254 padlen += pad;
1255 /* Check whether padlen calculation overflowed */
1256 if (padlen < tmp)
1257 return SSH_ERR_INVALID_ARGUMENT; /* overflow */
1211 state->extra_pad = 0; 1258 state->extra_pad = 0;
1212 } 1259 }
1213 if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0) 1260 if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0)
@@ -1661,7 +1708,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1661{ 1708{
1662 struct session_state *state = ssh->state; 1709 struct session_state *state = ssh->state;
1663 u_int padlen, need; 1710 u_int padlen, need;
1664 u_char *cp, macbuf[SSH_DIGEST_MAX_LENGTH]; 1711 u_char *cp;
1665 u_int maclen, aadlen = 0, authlen = 0, block_size; 1712 u_int maclen, aadlen = 0, authlen = 0, block_size;
1666 struct sshenc *enc = NULL; 1713 struct sshenc *enc = NULL;
1667 struct sshmac *mac = NULL; 1714 struct sshmac *mac = NULL;
@@ -1726,8 +1773,8 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1726 sshbuf_dump(state->incoming_packet, stderr); 1773 sshbuf_dump(state->incoming_packet, stderr);
1727#endif 1774#endif
1728 logit("Bad packet length %u.", state->packlen); 1775 logit("Bad packet length %u.", state->packlen);
1729 return ssh_packet_start_discard(ssh, enc, mac, 1776 return ssh_packet_start_discard(ssh, enc, mac, 0,
1730 state->packlen, PACKET_MAX_SIZE); 1777 PACKET_MAX_SIZE);
1731 } 1778 }
1732 if ((r = sshbuf_consume(state->input, block_size)) != 0) 1779 if ((r = sshbuf_consume(state->input, block_size)) != 0)
1733 goto out; 1780 goto out;
@@ -1749,8 +1796,8 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1749 if (need % block_size != 0) { 1796 if (need % block_size != 0) {
1750 logit("padding error: need %d block %d mod %d", 1797 logit("padding error: need %d block %d mod %d",
1751 need, block_size, need % block_size); 1798 need, block_size, need % block_size);
1752 return ssh_packet_start_discard(ssh, enc, mac, 1799 return ssh_packet_start_discard(ssh, enc, mac, 0,
1753 state->packlen, PACKET_MAX_SIZE - block_size); 1800 PACKET_MAX_SIZE - block_size);
1754 } 1801 }
1755 /* 1802 /*
1756 * check if the entire packet has been received and 1803 * check if the entire packet has been received and
@@ -1761,17 +1808,21 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1761 * 'maclen' bytes of message authentication code. 1808 * 'maclen' bytes of message authentication code.
1762 */ 1809 */
1763 if (sshbuf_len(state->input) < aadlen + need + authlen + maclen) 1810 if (sshbuf_len(state->input) < aadlen + need + authlen + maclen)
1764 return 0; 1811 return 0; /* packet is incomplete */
1765#ifdef PACKET_DEBUG 1812#ifdef PACKET_DEBUG
1766 fprintf(stderr, "read_poll enc/full: "); 1813 fprintf(stderr, "read_poll enc/full: ");
1767 sshbuf_dump(state->input, stderr); 1814 sshbuf_dump(state->input, stderr);
1768#endif 1815#endif
1769 /* EtM: compute mac over encrypted input */ 1816 /* EtM: check mac over encrypted input */
1770 if (mac && mac->enabled && mac->etm) { 1817 if (mac && mac->enabled && mac->etm) {
1771 if ((r = mac_compute(mac, state->p_read.seqnr, 1818 if ((r = mac_check(mac, state->p_read.seqnr,
1772 sshbuf_ptr(state->input), aadlen + need, 1819 sshbuf_ptr(state->input), aadlen + need,
1773 macbuf, sizeof(macbuf))) != 0) 1820 sshbuf_ptr(state->input) + aadlen + need + authlen,
1821 maclen)) != 0) {
1822 if (r == SSH_ERR_MAC_INVALID)
1823 logit("Corrupted MAC on input.");
1774 goto out; 1824 goto out;
1825 }
1775 } 1826 }
1776 if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need, 1827 if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need,
1777 &cp)) != 0) 1828 &cp)) != 0)
@@ -1781,26 +1832,22 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1781 goto out; 1832 goto out;
1782 if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0) 1833 if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0)
1783 goto out; 1834 goto out;
1784 /*
1785 * compute MAC over seqnr and packet,
1786 * increment sequence number for incoming packet
1787 */
1788 if (mac && mac->enabled) { 1835 if (mac && mac->enabled) {
1789 if (!mac->etm) 1836 /* Not EtM: check MAC over cleartext */
1790 if ((r = mac_compute(mac, state->p_read.seqnr, 1837 if (!mac->etm && (r = mac_check(mac, state->p_read.seqnr,
1791 sshbuf_ptr(state->incoming_packet), 1838 sshbuf_ptr(state->incoming_packet),
1792 sshbuf_len(state->incoming_packet), 1839 sshbuf_len(state->incoming_packet),
1793 macbuf, sizeof(macbuf))) != 0) 1840 sshbuf_ptr(state->input), maclen)) != 0) {
1841 if (r != SSH_ERR_MAC_INVALID)
1794 goto out; 1842 goto out;
1795 if (timingsafe_bcmp(macbuf, sshbuf_ptr(state->input),
1796 mac->mac_len) != 0) {
1797 logit("Corrupted MAC on input."); 1843 logit("Corrupted MAC on input.");
1798 if (need > PACKET_MAX_SIZE) 1844 if (need > PACKET_MAX_SIZE)
1799 return SSH_ERR_INTERNAL_ERROR; 1845 return SSH_ERR_INTERNAL_ERROR;
1800 return ssh_packet_start_discard(ssh, enc, mac, 1846 return ssh_packet_start_discard(ssh, enc, mac,
1801 state->packlen, PACKET_MAX_SIZE - need); 1847 sshbuf_len(state->incoming_packet),
1848 PACKET_MAX_SIZE - need);
1802 } 1849 }
1803 1850 /* Remove MAC from input buffer */
1804 DBG(debug("MAC #%d ok", state->p_read.seqnr)); 1851 DBG(debug("MAC #%d ok", state->p_read.seqnr));
1805 if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0) 1852 if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
1806 goto out; 1853 goto out;
@@ -2045,24 +2092,19 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
2045{ 2092{
2046 switch (r) { 2093 switch (r) {
2047 case SSH_ERR_CONN_CLOSED: 2094 case SSH_ERR_CONN_CLOSED:
2048 logit("Connection closed by %.200s port %d", 2095 logdie("Connection closed by %.200s port %d",
2049 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); 2096 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
2050 cleanup_exit(255);
2051 case SSH_ERR_CONN_TIMEOUT: 2097 case SSH_ERR_CONN_TIMEOUT:
2052 logit("Connection %s %.200s port %d timed out", 2098 logdie("Connection %s %.200s port %d timed out",
2053 ssh->state->server_side ? "from" : "to", 2099 ssh->state->server_side ? "from" : "to",
2054 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); 2100 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
2055 cleanup_exit(255);
2056 case SSH_ERR_DISCONNECTED: 2101 case SSH_ERR_DISCONNECTED:
2057 logit("Disconnected from %.200s port %d", 2102 logdie("Disconnected from %.200s port %d",
2058 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); 2103 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
2059 cleanup_exit(255);
2060 case SSH_ERR_SYSTEM_ERROR: 2104 case SSH_ERR_SYSTEM_ERROR:
2061 if (errno == ECONNRESET) { 2105 if (errno == ECONNRESET)
2062 logit("Connection reset by %.200s port %d", 2106 logdie("Connection reset by %.200s port %d",
2063 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); 2107 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
2064 cleanup_exit(255);
2065 }
2066 /* FALLTHROUGH */ 2108 /* FALLTHROUGH */
2067 case SSH_ERR_NO_CIPHER_ALG_MATCH: 2109 case SSH_ERR_NO_CIPHER_ALG_MATCH:
2068 case SSH_ERR_NO_MAC_ALG_MATCH: 2110 case SSH_ERR_NO_MAC_ALG_MATCH:
@@ -2070,14 +2112,14 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
2070 case SSH_ERR_NO_KEX_ALG_MATCH: 2112 case SSH_ERR_NO_KEX_ALG_MATCH:
2071 case SSH_ERR_NO_HOSTKEY_ALG_MATCH: 2113 case SSH_ERR_NO_HOSTKEY_ALG_MATCH:
2072 if (ssh && ssh->kex && ssh->kex->failed_choice) { 2114 if (ssh && ssh->kex && ssh->kex->failed_choice) {
2073 fatal("Unable to negotiate with %.200s port %d: %s. " 2115 logdie("Unable to negotiate with %.200s port %d: %s. "
2074 "Their offer: %s", ssh_remote_ipaddr(ssh), 2116 "Their offer: %s", ssh_remote_ipaddr(ssh),
2075 ssh_remote_port(ssh), ssh_err(r), 2117 ssh_remote_port(ssh), ssh_err(r),
2076 ssh->kex->failed_choice); 2118 ssh->kex->failed_choice);
2077 } 2119 }
2078 /* FALLTHROUGH */ 2120 /* FALLTHROUGH */
2079 default: 2121 default:
2080 fatal("%s%sConnection %s %.200s port %d: %s", 2122 logdie("%s%sConnection %s %.200s port %d: %s",
2081 tag != NULL ? tag : "", tag != NULL ? ": " : "", 2123 tag != NULL ? tag : "", tag != NULL ? ": " : "",
2082 ssh->state->server_side ? "from" : "to", 2124 ssh->state->server_side ? "from" : "to",
2083 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), ssh_err(r)); 2125 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), ssh_err(r));