]> andersk Git - openssh.git/blobdiff - packet.c
- stevesk@cvs.openbsd.org 2006/02/08 14:38:18
[openssh.git] / packet.c
index fca0075e77fab249140ae2f6592696dc8ebfc908..24d2bb312be1baf90f49c7e2712b7c19ed1c0e53 100644 (file)
--- a/packet.c
+++ b/packet.c
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: packet.c,v 1.114 2004/06/14 01:44:39 djm Exp $");
-
+RCSID("$OpenBSD: packet.c,v 1.121 2006/02/08 14:38:18 stevesk Exp $");
 #include "openbsd-compat/sys-queue.h"
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
 
 #include "xmalloc.h"
 #include "buffer.h"
@@ -116,6 +118,12 @@ static int initialized = 0;
 /* Set to true if the connection is interactive. */
 static int interactive_mode = 0;
 
+/* Set to true if we are the server side. */
+static int server_side = 0;
+
+/* Set to true if we are authenticated. */
+static int after_authentication = 0;
+
 /* Session key information for Encryption and MAC */
 Newkeys *newkeys[MODE_MAX];
 static struct packet_state {
@@ -507,7 +515,7 @@ packet_send1(void)
        u_char buf[8], *cp;
        int i, padding, len;
        u_int checksum;
-       u_int32_t rand = 0;
+       u_int32_t rnd = 0;
 
        /*
         * If using packet compression, compress the payload of the outgoing
@@ -533,9 +541,9 @@ packet_send1(void)
                cp = buffer_ptr(&outgoing_packet);
                for (i = 0; i < padding; i++) {
                        if (i % 4 == 0)
-                               rand = arc4random();
-                       cp[7 - i] = rand & 0xff;
-                       rand >>= 8;
+                               rnd = arc4random();
+                       cp[7 - i] = rnd & 0xff;
+                       rnd >>= 8;
                }
        }
        buffer_consume(&outgoing_packet, 8 - padding);
@@ -566,7 +574,7 @@ packet_send1(void)
        buffer_clear(&outgoing_packet);
 
        /*
-        * Note that the packet is now only buffered in output.  It won\'t be
+        * Note that the packet is now only buffered in output.  It won't be
         * actually sent until packet_write_wait or packet_write_poll is
         * called.
         */
@@ -580,18 +588,18 @@ set_newkeys(int mode)
        Comp *comp;
        CipherContext *cc;
        u_int64_t *max_blocks;
-       int encrypt;
+       int crypt_type;
 
        debug2("set_newkeys: mode %d", mode);
 
        if (mode == MODE_OUT) {
                cc = &send_context;
-               encrypt = CIPHER_ENCRYPT;
+               crypt_type = CIPHER_ENCRYPT;
                p_send.packets = p_send.blocks = 0;
                max_blocks = &max_blocks_out;
        } else {
                cc = &receive_context;
-               encrypt = CIPHER_DECRYPT;
+               crypt_type = CIPHER_DECRYPT;
                p_read.packets = p_read.blocks = 0;
                max_blocks = &max_blocks_in;
        }
@@ -620,11 +628,13 @@ set_newkeys(int mode)
                mac->enabled = 1;
        DBG(debug("cipher_init_context: %d", mode));
        cipher_init(cc, enc->cipher, enc->key, enc->key_len,
-           enc->iv, enc->block_size, encrypt);
+           enc->iv, enc->block_size, crypt_type);
        /* Deleting the keys does not gain extra security */
        /* memset(enc->iv,  0, enc->block_size);
           memset(enc->key, 0, enc->key_len); */
-       if (comp->type != 0 && comp->enabled == 0) {
+       if ((comp->type == COMP_ZLIB ||
+           (comp->type == COMP_DELAYED && after_authentication)) &&
+           comp->enabled == 0) {
                packet_init_compression();
                if (mode == MODE_OUT)
                        buffer_compress_init_send(6);
@@ -644,6 +654,35 @@ set_newkeys(int mode)
                *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size);
 }
 
+/*
+ * Delayed compression for SSH2 is enabled after authentication:
+ * This happans on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent,
+ * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received.
+ */
+static void
+packet_enable_delayed_compress(void)
+{
+       Comp *comp = NULL;
+       int mode;
+
+       /*
+        * Remember that we are past the authentication step, so rekeying
+        * with COMP_DELAYED will turn on compression immediately.
+        */
+       after_authentication = 1;
+       for (mode = 0; mode < MODE_MAX; mode++) {
+               comp = &newkeys[mode]->comp;
+               if (comp && !comp->enabled && comp->type == COMP_DELAYED) {
+                       packet_init_compression();
+                       if (mode == MODE_OUT)
+                               buffer_compress_init_send(6);
+                       else
+                               buffer_compress_init_recv();
+                       comp->enabled = 1;
+               }
+       }
+}
+
 /*
  * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
  */
@@ -654,7 +693,7 @@ packet_send2_wrapped(void)
        u_char padlen, pad;
        u_int packet_length = 0;
        u_int i, len;
-       u_int32_t rand = 0;
+       u_int32_t rnd = 0;
        Enc *enc   = NULL;
        Mac *mac   = NULL;
        Comp *comp = NULL;
@@ -713,9 +752,9 @@ packet_send2_wrapped(void)
                /* random padding */
                for (i = 0; i < padlen; i++) {
                        if (i % 4 == 0)
-                               rand = arc4random();
-                       cp[i] = rand & 0xff;
-                       rand >>= 8;
+                               rnd = arc4random();
+                       cp[i] = rnd & 0xff;
+                       rnd >>= 8;
                }
        } else {
                /* clear padding */
@@ -757,6 +796,8 @@ packet_send2_wrapped(void)
 
        if (type == SSH2_MSG_NEWKEYS)
                set_newkeys(MODE_OUT);
+       else if (type == SSH2_MSG_USERAUTH_SUCCESS && server_side)
+               packet_enable_delayed_compress();
 }
 
 static void
@@ -981,6 +1022,8 @@ packet_read_poll1(void)
                    buffer_len(&compression_buffer));
        }
        type = buffer_get_char(&incoming_packet);
+       if (type < SSH_MSG_MIN || type > SSH_MSG_MAX)
+               packet_disconnect("Invalid ssh1 packet type: %d", type);
        return type;
 }
 
@@ -990,7 +1033,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
        static u_int packet_length = 0;
        u_int padlen, need;
        u_char *macbuf, *cp, type;
-       int maclen, block_size;
+       u_int maclen, block_size;
        Enc *enc   = NULL;
        Mac *mac   = NULL;
        Comp *comp = NULL;
@@ -1093,8 +1136,12 @@ packet_read_poll2(u_int32_t *seqnr_p)
         * return length of payload (without type field)
         */
        type = buffer_get_char(&incoming_packet);
+       if (type < SSH2_MSG_MIN || type >= SSH2_MSG_LOCAL_MIN)
+               packet_disconnect("Invalid ssh2 packet type: %d", type);
        if (type == SSH2_MSG_NEWKEYS)
                set_newkeys(MODE_IN);
+       else if (type == SSH2_MSG_USERAUTH_SUCCESS && !server_side)
+               packet_enable_delayed_compress();
 #ifdef PACKET_DEBUG
        fprintf(stderr, "read/plain[%d]:\r\n", type);
        buffer_dump(&incoming_packet);
@@ -1225,9 +1272,9 @@ packet_get_bignum2(BIGNUM * value)
 }
 
 void *
-packet_get_raw(int *length_ptr)
+packet_get_raw(u_int *length_ptr)
 {
-       int bytes = buffer_len(&incoming_packet);
+       u_int bytes = buffer_len(&incoming_packet);
 
        if (length_ptr != NULL)
                *length_ptr = bytes;
@@ -1489,16 +1536,16 @@ packet_add_padding(u_char pad)
 void
 packet_send_ignore(int nbytes)
 {
-       u_int32_t rand = 0;
+       u_int32_t rnd = 0;
        int i;
 
        packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE);
        packet_put_int(nbytes);
        for (i = 0; i < nbytes; i++) {
                if (i % 4 == 0)
-                       rand = arc4random();
-               packet_put_char(rand & 0xff);
-               rand >>= 8;
+                       rnd = arc4random();
+               packet_put_char(rnd & 0xff);
+               rnd >>= 8;
        }
 }
 
@@ -1520,3 +1567,15 @@ packet_set_rekey_limit(u_int32_t bytes)
 {
        rekey_limit = bytes;
 }
+
+void
+packet_set_server(void)
+{
+       server_side = 1;
+}
+
+void
+packet_set_authenticated(void)
+{
+       after_authentication = 1;
+}
This page took 0.064832 seconds and 4 git commands to generate.