diff options
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 154 |
1 files changed, 115 insertions, 39 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.227 2016/02/04 23:43:48 djm Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.228 2016/02/08 10:57:07 djm 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 |
@@ -259,6 +259,14 @@ ssh_alloc_session_state(void) | |||
259 | return NULL; | 259 | return NULL; |
260 | } | 260 | } |
261 | 261 | ||
262 | /* Returns nonzero if rekeying is in progress */ | ||
263 | int | ||
264 | ssh_packet_is_rekeying(struct ssh *ssh) | ||
265 | { | ||
266 | return ssh->state->rekeying || | ||
267 | (ssh->kex != NULL && ssh->kex->done == 0); | ||
268 | } | ||
269 | |||
262 | /* | 270 | /* |
263 | * Sets the descriptors used for communication. Disables encryption until | 271 | * Sets the descriptors used for communication. Disables encryption until |
264 | * packet_set_encryption_key is called. | 272 | * packet_set_encryption_key is called. |
@@ -1029,6 +1037,51 @@ ssh_set_newkeys(struct ssh *ssh, int mode) | |||
1029 | return 0; | 1037 | return 0; |
1030 | } | 1038 | } |
1031 | 1039 | ||
1040 | #define MAX_PACKETS (1U<<31) | ||
1041 | static int | ||
1042 | ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len) | ||
1043 | { | ||
1044 | struct session_state *state = ssh->state; | ||
1045 | u_int32_t out_blocks; | ||
1046 | |||
1047 | /* XXX client can't cope with rekeying pre-auth */ | ||
1048 | if (!state->after_authentication) | ||
1049 | return 0; | ||
1050 | |||
1051 | /* Haven't keyed yet or KEX in progress. */ | ||
1052 | if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh)) | ||
1053 | return 0; | ||
1054 | |||
1055 | /* Peer can't rekey */ | ||
1056 | if (ssh->compat & SSH_BUG_NOREKEY) | ||
1057 | return 0; | ||
1058 | |||
1059 | /* | ||
1060 | * Permit one packet in or out per rekey - this allows us to | ||
1061 | * make progress when rekey limits are very small. | ||
1062 | */ | ||
1063 | if (state->p_send.packets == 0 && state->p_read.packets == 0) | ||
1064 | return 0; | ||
1065 | |||
1066 | /* Time-based rekeying */ | ||
1067 | if (state->rekey_interval != 0 && | ||
1068 | state->rekey_time + state->rekey_interval <= monotime()) | ||
1069 | return 1; | ||
1070 | |||
1071 | /* Always rekey when MAX_PACKETS sent in either direction */ | ||
1072 | if (state->p_send.packets > MAX_PACKETS || | ||
1073 | state->p_read.packets > MAX_PACKETS) | ||
1074 | return 1; | ||
1075 | |||
1076 | /* Rekey after (cipher-specific) maxiumum blocks */ | ||
1077 | out_blocks = roundup(outbound_packet_len, | ||
1078 | state->newkeys[MODE_OUT]->enc.block_size); | ||
1079 | return (state->max_blocks_out && | ||
1080 | (state->p_send.blocks + out_blocks > state->max_blocks_out)) || | ||
1081 | (state->max_blocks_in && | ||
1082 | (state->p_read.blocks > state->max_blocks_in)); | ||
1083 | } | ||
1084 | |||
1032 | /* | 1085 | /* |
1033 | * Delayed compression for SSH2 is enabled after authentication: | 1086 | * Delayed compression for SSH2 is enabled after authentication: |
1034 | * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent, | 1087 | * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent, |
@@ -1232,35 +1285,58 @@ ssh_packet_send2_wrapped(struct ssh *ssh) | |||
1232 | return r; | 1285 | return r; |
1233 | } | 1286 | } |
1234 | 1287 | ||
1288 | /* returns non-zero if the specified packet type is usec by KEX */ | ||
1289 | static int | ||
1290 | ssh_packet_type_is_kex(u_char type) | ||
1291 | { | ||
1292 | return | ||
1293 | type >= SSH2_MSG_TRANSPORT_MIN && | ||
1294 | type <= SSH2_MSG_TRANSPORT_MAX && | ||
1295 | type != SSH2_MSG_SERVICE_REQUEST && | ||
1296 | type != SSH2_MSG_SERVICE_ACCEPT && | ||
1297 | type != SSH2_MSG_EXT_INFO; | ||
1298 | } | ||
1299 | |||
1235 | int | 1300 | int |
1236 | ssh_packet_send2(struct ssh *ssh) | 1301 | ssh_packet_send2(struct ssh *ssh) |
1237 | { | 1302 | { |
1238 | struct session_state *state = ssh->state; | 1303 | struct session_state *state = ssh->state; |
1239 | struct packet *p; | 1304 | struct packet *p; |
1240 | u_char type; | 1305 | u_char type; |
1241 | int r; | 1306 | int r, need_rekey; |
1242 | 1307 | ||
1308 | if (sshbuf_len(state->outgoing_packet) < 6) | ||
1309 | return SSH_ERR_INTERNAL_ERROR; | ||
1243 | type = sshbuf_ptr(state->outgoing_packet)[5]; | 1310 | type = sshbuf_ptr(state->outgoing_packet)[5]; |
1311 | need_rekey = !ssh_packet_type_is_kex(type) && | ||
1312 | ssh_packet_need_rekeying(ssh, sshbuf_len(state->outgoing_packet)); | ||
1244 | 1313 | ||
1245 | /* during rekeying we can only send key exchange messages */ | 1314 | /* |
1246 | if (state->rekeying) { | 1315 | * During rekeying we can only send key exchange messages. |
1247 | if ((type < SSH2_MSG_TRANSPORT_MIN) || | 1316 | * Queue everything else. |
1248 | (type > SSH2_MSG_TRANSPORT_MAX) || | 1317 | */ |
1249 | (type == SSH2_MSG_SERVICE_REQUEST) || | 1318 | if ((need_rekey || state->rekeying) && !ssh_packet_type_is_kex(type)) { |
1250 | (type == SSH2_MSG_SERVICE_ACCEPT) || | 1319 | if (need_rekey) |
1251 | (type == SSH2_MSG_EXT_INFO)) { | 1320 | debug3("%s: rekex triggered", __func__); |
1252 | debug("enqueue packet: %u", type); | 1321 | debug("enqueue packet: %u", type); |
1253 | p = calloc(1, sizeof(*p)); | 1322 | p = calloc(1, sizeof(*p)); |
1254 | if (p == NULL) | 1323 | if (p == NULL) |
1255 | return SSH_ERR_ALLOC_FAIL; | 1324 | return SSH_ERR_ALLOC_FAIL; |
1256 | p->type = type; | 1325 | p->type = type; |
1257 | p->payload = state->outgoing_packet; | 1326 | p->payload = state->outgoing_packet; |
1258 | TAILQ_INSERT_TAIL(&state->outgoing, p, next); | 1327 | TAILQ_INSERT_TAIL(&state->outgoing, p, next); |
1259 | state->outgoing_packet = sshbuf_new(); | 1328 | state->outgoing_packet = sshbuf_new(); |
1260 | if (state->outgoing_packet == NULL) | 1329 | if (state->outgoing_packet == NULL) |
1261 | return SSH_ERR_ALLOC_FAIL; | 1330 | return SSH_ERR_ALLOC_FAIL; |
1262 | return 0; | 1331 | if (need_rekey) { |
1332 | /* | ||
1333 | * This packet triggered a rekey, so send the | ||
1334 | * KEXINIT now. | ||
1335 | * NB. reenters this function via kex_start_rekex(). | ||
1336 | */ | ||
1337 | return kex_start_rekex(ssh); | ||
1263 | } | 1338 | } |
1339 | return 0; | ||
1264 | } | 1340 | } |
1265 | 1341 | ||
1266 | /* rekeying starts with sending KEXINIT */ | 1342 | /* rekeying starts with sending KEXINIT */ |
@@ -1276,10 +1352,22 @@ ssh_packet_send2(struct ssh *ssh) | |||
1276 | state->rekey_time = monotime(); | 1352 | state->rekey_time = monotime(); |
1277 | while ((p = TAILQ_FIRST(&state->outgoing))) { | 1353 | while ((p = TAILQ_FIRST(&state->outgoing))) { |
1278 | type = p->type; | 1354 | type = p->type; |
1355 | /* | ||
1356 | * If this packet triggers a rekex, then skip the | ||
1357 | * remaining packets in the queue for now. | ||
1358 | * NB. re-enters this function via kex_start_rekex. | ||
1359 | */ | ||
1360 | if (ssh_packet_need_rekeying(ssh, | ||
1361 | sshbuf_len(p->payload))) { | ||
1362 | debug3("%s: queued packet triggered rekex", | ||
1363 | __func__); | ||
1364 | return kex_start_rekex(ssh); | ||
1365 | } | ||
1279 | debug("dequeue packet: %u", type); | 1366 | debug("dequeue packet: %u", type); |
1280 | sshbuf_free(state->outgoing_packet); | 1367 | sshbuf_free(state->outgoing_packet); |
1281 | state->outgoing_packet = p->payload; | 1368 | state->outgoing_packet = p->payload; |
1282 | TAILQ_REMOVE(&state->outgoing, p, next); | 1369 | TAILQ_REMOVE(&state->outgoing, p, next); |
1370 | memset(p, 0, sizeof(*p)); | ||
1283 | free(p); | 1371 | free(p); |
1284 | if ((r = ssh_packet_send2_wrapped(ssh)) != 0) | 1372 | if ((r = ssh_packet_send2_wrapped(ssh)) != 0) |
1285 | return r; | 1373 | return r; |
@@ -1784,6 +1872,13 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1784 | #endif | 1872 | #endif |
1785 | /* reset for next packet */ | 1873 | /* reset for next packet */ |
1786 | state->packlen = 0; | 1874 | state->packlen = 0; |
1875 | |||
1876 | /* do we need to rekey? */ | ||
1877 | if (ssh_packet_need_rekeying(ssh, 0)) { | ||
1878 | debug3("%s: rekex triggered", __func__); | ||
1879 | if ((r = kex_start_rekex(ssh)) != 0) | ||
1880 | return r; | ||
1881 | } | ||
1787 | out: | 1882 | out: |
1788 | return r; | 1883 | return r; |
1789 | } | 1884 | } |
@@ -2268,25 +2363,6 @@ ssh_packet_send_ignore(struct ssh *ssh, int nbytes) | |||
2268 | } | 2363 | } |
2269 | } | 2364 | } |
2270 | 2365 | ||
2271 | #define MAX_PACKETS (1U<<31) | ||
2272 | int | ||
2273 | ssh_packet_need_rekeying(struct ssh *ssh) | ||
2274 | { | ||
2275 | struct session_state *state = ssh->state; | ||
2276 | |||
2277 | if (ssh->compat & SSH_BUG_NOREKEY) | ||
2278 | return 0; | ||
2279 | return | ||
2280 | (state->p_send.packets > MAX_PACKETS) || | ||
2281 | (state->p_read.packets > MAX_PACKETS) || | ||
2282 | (state->max_blocks_out && | ||
2283 | (state->p_send.blocks > state->max_blocks_out)) || | ||
2284 | (state->max_blocks_in && | ||
2285 | (state->p_read.blocks > state->max_blocks_in)) || | ||
2286 | (state->rekey_interval != 0 && state->rekey_time + | ||
2287 | state->rekey_interval <= monotime()); | ||
2288 | } | ||
2289 | |||
2290 | void | 2366 | void |
2291 | ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, time_t seconds) | 2367 | ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, time_t seconds) |
2292 | { | 2368 | { |