summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--cipher.c49
-rw-r--r--cipher.h3
-rw-r--r--packet.c72
4 files changed, 102 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index 1ce3a84b8..8584ff316 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -80,6 +80,12 @@
80 - naddy@cvs.openbsd.org 2009/01/24 17:10:22 80 - naddy@cvs.openbsd.org 2009/01/24 17:10:22
81 [ssh_config.5 sshd_config.5] 81 [ssh_config.5 sshd_config.5]
82 sync list of preferred ciphers; ok djm@ 82 sync list of preferred ciphers; ok djm@
83 - markus@cvs.openbsd.org 2009/01/26 09:58:15
84 [cipher.c cipher.h packet.c]
85 Work around the CPNI-957037 Plaintext Recovery Attack by always
86 reading 256K of data on packet size or HMAC errors (in CBC mode only).
87 Help, feedback and ok djm@
88 Feedback from Martin Albrecht and Paterson Kenny
83 89
8420090107 9020090107
85 - (djm) [uidswap.c] bz#1412: Support >16 supplemental groups in OS X. 91 - (djm) [uidswap.c] bz#1412: Support >16 supplemental groups in OS X.
@@ -5089,5 +5095,5 @@
5089 OpenServer 6 and add osr5bigcrypt support so when someone migrates 5095 OpenServer 6 and add osr5bigcrypt support so when someone migrates
5090 passwords between UnixWare and OpenServer they will still work. OK dtucker@ 5096 passwords between UnixWare and OpenServer they will still work. OK dtucker@
5091 5097
5092$Id: ChangeLog,v 1.5178 2009/01/28 05:34:00 djm Exp $ 5098$Id: ChangeLog,v 1.5179 2009/01/28 05:38:41 djm Exp $
5093 5099
diff --git a/cipher.c b/cipher.c
index b264063c4..bb5c0ac3a 100644
--- a/cipher.c
+++ b/cipher.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher.c,v 1.81 2006/08/03 03:34:42 deraadt Exp $ */ 1/* $OpenBSD: cipher.c,v 1.82 2009/01/26 09:58:15 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
@@ -63,31 +63,32 @@ struct Cipher {
63 u_int block_size; 63 u_int block_size;
64 u_int key_len; 64 u_int key_len;
65 u_int discard_len; 65 u_int discard_len;
66 u_int cbc_mode;
66 const EVP_CIPHER *(*evptype)(void); 67 const EVP_CIPHER *(*evptype)(void);
67} ciphers[] = { 68} ciphers[] = {
68 { "none", SSH_CIPHER_NONE, 8, 0, 0, EVP_enc_null }, 69 { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null },
69 { "des", SSH_CIPHER_DES, 8, 8, 0, EVP_des_cbc }, 70 { "des", SSH_CIPHER_DES, 8, 8, 0, 1, EVP_des_cbc },
70 { "3des", SSH_CIPHER_3DES, 8, 16, 0, evp_ssh1_3des }, 71 { "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des },
71 { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, evp_ssh1_bf }, 72 { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 1, evp_ssh1_bf },
72 73
73 { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, EVP_des_ede3_cbc }, 74 { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc },
74 { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_bf_cbc }, 75 { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_bf_cbc },
75 { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, EVP_cast5_cbc }, 76 { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_cast5_cbc },
76 { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, EVP_rc4 }, 77 { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, EVP_rc4 },
77 { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, EVP_rc4 }, 78 { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, 0, EVP_rc4 },
78 { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, EVP_rc4 }, 79 { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, 0, EVP_rc4 },
79 { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, EVP_aes_128_cbc }, 80 { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc },
80 { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, EVP_aes_192_cbc }, 81 { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc },
81 { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc }, 82 { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
82 { "rijndael-cbc@lysator.liu.se", 83 { "rijndael-cbc@lysator.liu.se",
83 SSH_CIPHER_SSH2, 16, 32, 0, EVP_aes_256_cbc }, 84 SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
84 { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, evp_aes_128_ctr }, 85 { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr },
85 { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, evp_aes_128_ctr }, 86 { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr },
86 { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, evp_aes_128_ctr }, 87 { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr },
87#ifdef USE_CIPHER_ACSS 88#ifdef USE_CIPHER_ACSS
88 { "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, EVP_acss }, 89 { "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, 0, EVP_acss },
89#endif 90#endif
90 { NULL, SSH_CIPHER_INVALID, 0, 0, 0, NULL } 91 { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL }
91}; 92};
92 93
93/*--*/ 94/*--*/
@@ -111,6 +112,12 @@ cipher_get_number(const Cipher *c)
111} 112}
112 113
113u_int 114u_int
115cipher_is_cbc(const Cipher *c)
116{
117 return (c->cbc_mode);
118}
119
120u_int
114cipher_mask_ssh1(int client) 121cipher_mask_ssh1(int client)
115{ 122{
116 u_int mask = 0; 123 u_int mask = 0;
diff --git a/cipher.h b/cipher.h
index 49bbc1682..3dd2270bb 100644
--- a/cipher.h
+++ b/cipher.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher.h,v 1.36 2006/03/25 22:22:42 djm Exp $ */ 1/* $OpenBSD: cipher.h,v 1.37 2009/01/26 09:58:15 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -81,6 +81,7 @@ void cipher_cleanup(CipherContext *);
81void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); 81void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
82u_int cipher_blocksize(const Cipher *); 82u_int cipher_blocksize(const Cipher *);
83u_int cipher_keylen(const Cipher *); 83u_int cipher_keylen(const Cipher *);
84u_int cipher_is_cbc(const Cipher *);
84 85
85u_int cipher_get_number(const Cipher *); 86u_int cipher_get_number(const Cipher *);
86void cipher_get_keyiv(CipherContext *, u_char *, u_int); 87void cipher_get_keyiv(CipherContext *, u_char *, u_int);
diff --git a/packet.c b/packet.c
index 4ded17fac..33559cd4f 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.158 2008/11/21 15:47:38 markus Exp $ */ 1/* $OpenBSD: packet.c,v 1.159 2009/01/26 09:58:15 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 (!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