comparison packet.c @ 452:4cab61369879

Prevent invalid packets being sent during key-exchange, instead queue them until afterwards. This could sometimes terminate connections after 8 hours if (for example) a new TCP forwarded connection was sent at the KEX timeout.
author Matt Johnston <matt@ucc.asn.au>
date Fri, 27 Jul 2007 17:13:42 +0000
parents 9c61e7af0156
children 7e43f5e473b9
comparison
equal deleted inserted replaced
451:f2aa5aeea619 452:4cab61369879
401 } 401 }
402 } 402 }
403 #endif 403 #endif
404 404
405 405
406 406 /* returns 1 if the packet is a valid type during kex (see 7.1 of rfc4253) */
407 static int packet_is_okay_kex(unsigned char type) {
408 if (type >= SSH_MSG_USERAUTH_REQUEST) {
409 return 0;
410 }
411 if (type == SSH_MSG_SERVICE_REQUEST || type == SSH_MSG_SERVICE_ACCEPT) {
412 return 0;
413 }
414 if (type == SSH_MSG_KEXINIT) {
415 /* XXX should this die horribly if !dataallowed ?? */
416 return 0;
417 }
418 return 1;
419 }
420
421 static void enqueue_reply_packet() {
422 struct packetlist * new_item = NULL;
423 new_item = m_malloc(sizeof(struct packetlist));
424 new_item->next = NULL;
425
426 new_item->payload = buf_newcopy(ses.writepayload);
427 buf_setpos(ses.writepayload, 0);
428 buf_setlen(ses.writepayload, 0);
429
430 if (ses.reply_queue_tail) {
431 ses.reply_queue_tail->next = new_item;
432 } else {
433 ses.reply_queue_head = new_item;
434 ses.reply_queue_tail = new_item;
435 }
436 TRACE(("leave enqueue_reply_packet"))
437 }
438
439 void maybe_flush_reply_queue() {
440 struct packetlist *tmp_item = NULL, *curr_item = NULL;
441 if (!ses.dataallowed)
442 {
443 TRACE(("maybe_empty_reply_queue - no data allowed"))
444 return;
445 }
446
447 for (curr_item = ses.reply_queue_head; curr_item; ) {
448 CHECKCLEARTOWRITE();
449 buf_putbytes(ses.writepayload,
450 curr_item->payload->data, curr_item->payload->len);
451
452 buf_free(curr_item->payload);
453 tmp_item = curr_item;
454 curr_item = curr_item->next;
455 m_free(tmp_item);
456 encrypt_packet();
457 }
458 ses.reply_queue_head = ses.reply_queue_tail = NULL;
459 }
407 460
408 /* encrypt the writepayload, putting into writebuf, ready for write_packet() 461 /* encrypt the writepayload, putting into writebuf, ready for write_packet()
409 * to put on the wire */ 462 * to put on the wire */
410 void encrypt_packet() { 463 void encrypt_packet() {
411 464
412 unsigned char padlen; 465 unsigned char padlen;
413 unsigned char blocksize, macsize; 466 unsigned char blocksize, macsize;
414 buffer * writebuf; /* the packet which will go on the wire */ 467 buffer * writebuf; /* the packet which will go on the wire */
415 buffer * clearwritebuf; /* unencrypted, possibly compressed */ 468 buffer * clearwritebuf; /* unencrypted, possibly compressed */
416 469 unsigned char type;
470
471 type = ses.writepayload->data[0];
417 TRACE(("enter encrypt_packet()")) 472 TRACE(("enter encrypt_packet()"))
418 TRACE(("encrypt_packet type is %d", ses.writepayload->data[0])) 473 TRACE(("encrypt_packet type is %d", type))
474
475 if (!ses.dataallowed && !packet_is_okay_kex(type)) {
476 /* During key exchange only particular packets are allowed.
477 Since this type isn't OK we just enqueue it to send
478 after the KEX, see maybe_flush_reply_queue */
479 enqueue_reply_packet();
480 return;
481 }
482
419 blocksize = ses.keys->trans_algo_crypt->blocksize; 483 blocksize = ses.keys->trans_algo_crypt->blocksize;
420 macsize = ses.keys->trans_algo_mac->hashsize; 484 macsize = ses.keys->trans_algo_mac->hashsize;
421 485
422 /* Encrypted packet len is payload+5, then worst case is if we are 3 away 486 /* Encrypted packet len is payload+5, then worst case is if we are 3 away
423 * from a blocksize multiple. In which case we need to pad to the 487 * from a blocksize multiple. In which case we need to pad to the