summaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2010-01-01 23:53:30 +0000
committerColin Watson <cjwatson@debian.org>2010-01-01 23:53:30 +0000
commitdf03186a4f9e0c2ece398b5c0571cb6263d7a752 (patch)
tree1aab079441dff9615274769b19f2d734ddf508dd /packet.c
parent6ad6994c288662fca6949f42bf91fec2aff00bca (diff)
parent99b402ea4c8457b0a3cafff37f5b3410a8dc6476 (diff)
* New upstream release (closes: #536182). Yes, I know 5.3p1 has been out
for a while, but there's no GSSAPI patch available for it yet. - Change the default cipher order to prefer the AES CTR modes and the revised "arcfour256" mode to CBC mode ciphers that are susceptible to CPNI-957037 "Plaintext Recovery Attack Against SSH". - Add countermeasures to mitigate CPNI-957037-style attacks against the SSH protocol's use of CBC-mode ciphers. Upon detection of an invalid packet length or Message Authentication Code, ssh/sshd will continue reading up to the maximum supported packet length rather than immediately terminating the connection. This eliminates most of the known differences in behaviour that leaked information about the plaintext of injected data which formed the basis of this attack (closes: #506115, LP: #379329). - ForceCommand directive now accepts commandline arguments for the internal-sftp server (closes: #524423, LP: #362511). - Add AllowAgentForwarding to available Match keywords list (closes: #540623). - Make ssh(1) send the correct channel number for SSH2_MSG_CHANNEL_SUCCESS and SSH2_MSG_CHANNEL_FAILURE messages to avoid triggering 'Non-public channel' error messages on sshd(8) in openssh-5.1. - Avoid printing 'Non-public channel' warnings in sshd(8), since the ssh(1) has sent incorrect channel numbers since ~2004 (this reverts a behaviour introduced in openssh-5.1; closes: #496017). * Update to GSSAPI patch from http://www.sxw.org.uk/computing/patches/openssh-5.2p1-gsskex-all-20090726.patch, including cascading credentials support (LP: #416958).
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c72
1 files changed, 65 insertions, 7 deletions
diff --git a/packet.c b/packet.c
index 3cb3decd9..5afc84ce0 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.157 2008/07/10 18:08:11 markus Exp $ */ 1/* $OpenBSD: packet.c,v 1.160 2009/02/13 11:50:21 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
@@ -84,6 +84,8 @@
84#define DBG(x) 84#define DBG(x)
85#endif 85#endif
86 86
87#define PACKET_MAX_SIZE (256 * 1024)
88
87/* 89/*
88 * This variable contains the file descriptors used for communicating with 90 * This variable contains the file descriptors used for communicating with
89 * the other side. connection_in is used for reading; connection_out for 91 * the other side. connection_in is used for reading; connection_out for
@@ -160,6 +162,10 @@ static u_int ssh1_keylen;
160/* roundup current message to extra_pad bytes */ 162/* roundup current message to extra_pad bytes */
161static u_char extra_pad = 0; 163static u_char extra_pad = 0;
162 164
165/* XXX discard incoming data after MAC error */
166static u_int packet_discard = 0;
167static Mac *packet_discard_mac = NULL;
168
163struct packet { 169struct packet {
164 TAILQ_ENTRY(packet) next; 170 TAILQ_ENTRY(packet) next;
165 u_char type; 171 u_char type;
@@ -209,6 +215,36 @@ packet_set_timeout(int timeout, int count)
209 packet_timeout_ms = timeout * count * 1000; 215 packet_timeout_ms = timeout * count * 1000;
210} 216}
211 217
218static void
219packet_stop_discard(void)
220{
221 if (packet_discard_mac) {
222 char buf[1024];
223
224 memset(buf, 'a', sizeof(buf));
225 while (buffer_len(&incoming_packet) < PACKET_MAX_SIZE)
226 buffer_append(&incoming_packet, buf, sizeof(buf));
227 (void) mac_compute(packet_discard_mac,
228 p_read.seqnr,
229 buffer_ptr(&incoming_packet),
230 PACKET_MAX_SIZE);
231 }
232 logit("Finished discarding for %.200s", get_remote_ipaddr());
233 cleanup_exit(255);
234}
235
236static void
237packet_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard)
238{
239 if (enc == NULL || !cipher_is_cbc(enc->cipher))
240 packet_disconnect("Packet corrupt");
241 if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled)
242 packet_discard_mac = mac;
243 if (buffer_len(&input) >= discard)
244 packet_stop_discard();
245 packet_discard = discard - buffer_len(&input);
246}
247
212/* Returns 1 if remote host is connected via socket, 0 if not. */ 248/* Returns 1 if remote host is connected via socket, 0 if not. */
213 249
214int 250int
@@ -1127,6 +1163,9 @@ packet_read_poll2(u_int32_t *seqnr_p)
1127 Mac *mac = NULL; 1163 Mac *mac = NULL;
1128 Comp *comp = NULL; 1164 Comp *comp = NULL;
1129 1165
1166 if (packet_discard)
1167 return SSH_MSG_NONE;
1168
1130 if (newkeys[MODE_IN] != NULL) { 1169 if (newkeys[MODE_IN] != NULL) {
1131 enc = &newkeys[MODE_IN]->enc; 1170 enc = &newkeys[MODE_IN]->enc;
1132 mac = &newkeys[MODE_IN]->mac; 1171 mac = &newkeys[MODE_IN]->mac;
@@ -1148,12 +1187,14 @@ packet_read_poll2(u_int32_t *seqnr_p)
1148 block_size); 1187 block_size);
1149 cp = buffer_ptr(&incoming_packet); 1188 cp = buffer_ptr(&incoming_packet);
1150 packet_length = get_u32(cp); 1189 packet_length = get_u32(cp);
1151 if (packet_length < 1 + 4 || packet_length > 256 * 1024) { 1190 if (packet_length < 1 + 4 || packet_length > PACKET_MAX_SIZE) {
1152#ifdef PACKET_DEBUG 1191#ifdef PACKET_DEBUG
1153 buffer_dump(&incoming_packet); 1192 buffer_dump(&incoming_packet);
1154#endif 1193#endif
1155 packet_disconnect("Bad packet length %-10u", 1194 logit("Bad packet length %u.", packet_length);
1156 packet_length); 1195 packet_start_discard(enc, mac, packet_length,
1196 PACKET_MAX_SIZE);
1197 return SSH_MSG_NONE;
1157 } 1198 }
1158 DBG(debug("input: packet len %u", packet_length+4)); 1199 DBG(debug("input: packet len %u", packet_length+4));
1159 buffer_consume(&input, block_size); 1200 buffer_consume(&input, block_size);
@@ -1165,7 +1206,9 @@ packet_read_poll2(u_int32_t *seqnr_p)
1165 if (need % block_size != 0) { 1206 if (need % block_size != 0) {
1166 logit("padding error: need %d block %d mod %d", 1207 logit("padding error: need %d block %d mod %d",
1167 need, block_size, need % block_size); 1208 need, block_size, need % block_size);
1168 packet_disconnect("Bad packet length %-10u", packet_length); 1209 packet_start_discard(enc, mac, packet_length,
1210 PACKET_MAX_SIZE - block_size);
1211 return SSH_MSG_NONE;
1169 } 1212 }
1170 /* 1213 /*
1171 * check if the entire packet has been received and 1214 * check if the entire packet has been received and
@@ -1188,11 +1231,19 @@ packet_read_poll2(u_int32_t *seqnr_p)
1188 macbuf = mac_compute(mac, p_read.seqnr, 1231 macbuf = mac_compute(mac, p_read.seqnr,
1189 buffer_ptr(&incoming_packet), 1232 buffer_ptr(&incoming_packet),
1190 buffer_len(&incoming_packet)); 1233 buffer_len(&incoming_packet));
1191 if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 1234 if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) {
1192 packet_disconnect("Corrupted MAC on input."); 1235 logit("Corrupted MAC on input.");
1236 if (need > PACKET_MAX_SIZE)
1237 fatal("internal error need %d", need);
1238 packet_start_discard(enc, mac, packet_length,
1239 PACKET_MAX_SIZE - need);
1240 return SSH_MSG_NONE;
1241 }
1242
1193 DBG(debug("MAC #%d ok", p_read.seqnr)); 1243 DBG(debug("MAC #%d ok", p_read.seqnr));
1194 buffer_consume(&input, mac->mac_len); 1244 buffer_consume(&input, mac->mac_len);
1195 } 1245 }
1246 /* XXX now it's safe to use fatal/packet_disconnect */
1196 if (seqnr_p != NULL) 1247 if (seqnr_p != NULL)
1197 *seqnr_p = p_read.seqnr; 1248 *seqnr_p = p_read.seqnr;
1198 if (++p_read.seqnr == 0) 1249 if (++p_read.seqnr == 0)
@@ -1325,6 +1376,13 @@ packet_read_poll(void)
1325void 1376void
1326packet_process_incoming(const char *buf, u_int len) 1377packet_process_incoming(const char *buf, u_int len)
1327{ 1378{
1379 if (packet_discard) {
1380 keep_alive_timeouts = 0; /* ?? */
1381 if (len >= packet_discard)
1382 packet_stop_discard();
1383 packet_discard -= len;
1384 return;
1385 }
1328 buffer_append(&input, buf, len); 1386 buffer_append(&input, buf, len);
1329} 1387}
1330 1388